c#socket 中怎么实现客户端分包发送数据,服务端分包接收数据的?

bluesliuf 2017-10-22 04:48:37
从客户端发来了一条很长的字符串数据,这种形式的:
WWW@@@ 3 3 ###@@@ 8 8 ###@@@ 8 8 ###@@@ 0 0 ###@@@ 6 6 ###@@@ 6 6 ###@@@ 1 1 ###@@@ 6 6 ###@@@ 3 3 ###@@@ 1 1 ###@@@ 0 0 ###@@@ 9 9 ### ....................MMM
WWW为包头,MMM为包尾,中间有多条@@@ 3 3 ###形式的数据
在服务端接受数据时,100,200都能接受到,1024条有时能接收到,大多接受不完全,会缺失包头和数据。
上网查询资料说是要客户端分包发送,然后服务端分包接收在拼接数据。
本人是一个小白,一点没学过c#,不知道大家有没有这样的好的实例,能让我快速了解学习一下。

客户端的程序是另一个人写的,他发字符串数据给我,我接受存入本地的一个txt文档。
以下是我写的服务端接受的程序,不知道怎么改进,希望大家多多指教!!

  private void bt_connnect_Click(object sender, EventArgs e)
{

try
{
//点击开始监听时 在服务端创建一个负责监听IP和端口号的Socket
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//指定IP地址
IPAddress ip = IPAddress.Any;
//创建对象端口
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(tb_port.Text));

socketWatch.Bind(point);//绑定端口号
ShowMsg("监听成功!");
socketWatch.Listen(10);//设置监听

//创建监听线程
Thread thread = new Thread(Listen);
thread.IsBackground = true;
thread.Start(socketWatch);
}
//收集异常信息
catch { }

}

/// <summary>
/// 等待客户端的连接 并且创建与之通信的Socket
/// </summary>
Socket socketSend;
void Listen(object o)
{
try
{
Socket socketWatch = o as Socket;
while (true)
{
socketSend = socketWatch.Accept();//等待接收客户端连接
//服务端显示连接状态信息
ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功!");
//开启一个新线程,执行接收消息方法
Thread r_thread = new Thread(Received);
r_thread.IsBackground = true;
r_thread.Start(socketSend);
}
}
catch { }
}
/// <summary>
/// 服务器端不停的接收客户端发来的消息
/// </summary>
/// <param name="o"></param>
void Received(object o)
{
try
{
Socket socketSend = o as Socket;
while (true)
{
//客户端连接服务器成功后,服务器接收客户端发送的消息,并将其存入缓冲区
byte[] buffer = new byte[1024 * 1024];
//实际接收到的有效字节数
int len = socketSend.Receive(buffer);
if (len == 0)
{
break;
}
//将缓冲区的字节数据转换成字符串
string str = Encoding.UTF8.GetString(buffer, 0, len);

//调用方法将数据写入你指定的路径文件中,此处测试用的是"D:\data\3.txt"路径文件
WriteStringToFile(@"D:\data\3.txt", str);
ShowMsg("存取数据成功!!");
}
}
catch { }
}
//将提示信息显示在listbox中
void ShowMsg(string msg)
{
listBox1.Items.Add(msg + "\r\n");
}
//将字符串数据写入指定的文件
public static void WriteStringToFile(string fileName, string contents)
{ //初始化一个写入流对象
StreamWriter sWriter = null;
try
{ // 使用指定的路径、创建模式和读/写权限初始化 FileStream 类的新实例
FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
//实例化写入流对象
sWriter = new StreamWriter(fileStream);
//将字符串写入流
sWriter.Write(contents);
}
finally
{
if (sWriter != null)
{ //关闭写入流
sWriter.Close();
}
}
}
...全文
923 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
凤凰居士 2017-11-16
  • 打赏
  • 举报
回复
网络传输中分包很正常的, 你们的问题在于通信设计很糟糕,最好重新设计下 目前你可采取下列方式补救下: 既然有包头和包尾,那就自己拼包,如果只收到包头没有包尾,说明还有数据没有到达,这个时候不要处理,等待剩余部分的到达,拼成一个完整的包再处理
  • 打赏
  • 举报
回复
接收数据流时,比如说客户端发送1000个字符(unicode 编码),有3000字节长度,那么你的服务器可能分2次分别接收2899和101个字节,你怎么可能在接收到2899个字节是就去执行
                     int len = socketSend.Receive(buffer);
                    if (len == 0)
                    {
                        break;
                    }
                    //将缓冲区的字节数据转换成字符串
                    string str = Encoding.UTF8.GetString(buffer, 0, len);
这里的 GetString 呢?这时候根本不保证接收到完整的一个字符,后边的 101 字节也不保证是以一个完整的字符开始的,这种编程逻辑是错误的。
酷python 2017-11-15
  • 打赏
  • 举报
回复
加我QQ,看私信

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧