在使用Socket进行网络编程的时候,一般都需要考虑一个包大小的问题。目前我们用得最大的情况是,每个包的大小为4KB(4096),但是,如果我们发送的数据要超过这个限制(这很常见),那么应该怎么办呢?
Socket本身并不提供对于这种情况的实现,一般我们需要自己拆包和组装。我下面写了一个例子
下面是发送一个文件的演示
服务端:
TcpListener server = null;
private void btListen_Click(object sender, EventArgs e)
{
ThreadStart info = new ThreadStart(StartListener);
Thread t = new Thread(info);
t.Start();
}
void StartListener()
{
server = new TcpListener(IPAddress.Any,8090);
try
{
server.Start();
while (true)
{
TcpClient client = server.AcceptTcpClient();
//直接给客户端发送一个图片
byte[] request = new byte[256];
int i;
if ((i=client.Client.Receive(request)) != 0)
{
string path = Encoding.UTF8.GetString(request,0,i).Trim();
//发送大文件
//1. 第一步:发送一个包,表示文件的长度,让客户端知道后续要接收几个包来重新组织成一个文件
FileStream fs = new FileStream(path, FileMode.Open);
long length = fs.Length;
client.Client.Send(Encoding.UTF8.GetBytes(length.ToString()));
//2. 第二步:每次发送一个4KB的包,如果文件较大,则会拆分为多个包
byte[] fileblock=new byte[4096];
while (fs.Read(fileblock,0,4096)!=0)
{
client.Client.Send(fileblock);
}
fs.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
客户端
private void btTransfom_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
client.Connect("localhost", 8090);
string request = @"e:\temp\test.jpg";
client.Client.Send(Encoding.UTF8.GetBytes(request));
byte[] result = new byte[4096];
client.Client.Receive(result);//收取第一个包,里面包含了文件的长度信息
int length = int.Parse(Encoding.UTF8.GetString(result));
byte[] file = new byte[4096];
int total = length;
MemoryStream ms = new MemoryStream();
while (total > 0)
{
int count = client.Client.Receive(file);
ms.Write(file, 0, count);
ms.Flush();
total -= count;
}
ms.Position = 0;
Bitmap bitmap = new Bitmap(ms);
pictureBox1.Image = bitmap;
}