记一次Socket编程踩的坑
闲来无事研究了下Socket,想用它做个简单的聊天室模型,结果踩了个坑,整半天才出来,惭愧啊,先上完成的代码吧
服务端:
public partial class Form1 : Form { public Form1() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ]; ]; List<Socket> clients = new List<Socket>(); private void btnBeginListen_Click(object sender, EventArgs e) { if(socket.LocalEndPoint!=null) { return; } IPEndPoint ip = new IPEndPoint(IPAddress.Any, int.Parse(tbPort.Text)); socket.Bind(ip); socket.Listen(); tbReceive.Text += "Begin listening...\r\n"; Task.Run(()=>BeginListen()); } private void BeginListen() { while (true) { Socket client = socket.Accept(); clients.Add(client); IPEndPoint clientIp = client.RemoteEndPoint as IPEndPoint; tbReceive.Text += clientIp.Address + ":" + clientIp.Port + " connected...\r\n"; receiveData = Encoding.UTF8.GetBytes("welcome"); client.Send(receiveData); Task.Run(() => ReceiveMsg(client)); } } private void ReceiveMsg(Socket client) { ; do { try { length = client.Receive(receiveData); , length); IPEndPoint ep = (IPEndPoint)client.RemoteEndPoint; tbReceive.Text += ep.Address + ":" + ep.Port + ": " + DateTime.Now.ToString() + "\r\n"; tbReceive.Text += stringData + "\r\n"; } catch (SocketException ex) { tbReceive.AppendText("远程端关闭.\r\n"); clients.Remove(client); return; } catch(Exception ex) { tbReceive.AppendText("异常:"+ex.Message); } } ); } private void btnSend_Click(object sender, EventArgs e) { Socket client = clients[]; sendData = Encoding.UTF8.GetBytes(tbSend.Text); client.Send(sendData, , sendData.Length,SocketFlags.None); tbSend.Clear(); } }
客户端:
public partial class Form1 : Form { public Form1() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ]; ]; private void btnConnect_Click(object sender, EventArgs e) { if(socket.LocalEndPoint!=null) { return; } IPEndPoint ip = new IPEndPoint(IPAddress.Any, int.Parse(tbLocalPort.Text)); socket.Bind(ip); IPEndPoint remoteIp = new IPEndPoint(IPAddress.Parse(tbIp.Text), int.Parse(tbPort.Text)); try { socket.Connect(remoteIp); } catch (Exception ex) { tbReceive.Text += "无法连接服务器:"+ex.Message; } Task.Run(() => ReceiveMsg()); } private void ReceiveMsg() { ; do { try { length = socket.Receive(receiveData); , length); IPEndPoint ep = (IPEndPoint)socket.RemoteEndPoint; tbReceive.Text += ep.Address + ":" + ep.Port + ": " + DateTime.Now.ToString() + "\r\n"; tbReceive.Text += stringData + "\r\n"; } catch (SocketException ex) { tbReceive.AppendText("连接异常.\r\n"); return; } catch (Exception ex) { tbReceive.AppendText("异常:" + ex.Message); } } ); } private void btnSend_Click(object sender, EventArgs e) { sendData = Encoding.UTF8.GetBytes(tbSend.Text); socket.Send(sendData, , sendData.Length, SocketFlags.None); tbSend.Clear(); } }
多线程写textbox的时候需要开启:TextBox.CheckForIllegalCrossThreadCalls = false;
好,下面问题来了:
请注意看这两行代码:
]; ];
开始一偷懒把这两个缓冲区用同一个数组来接收,然后坑就来了:
1.当我从服务端往客户端发了个“123”,客户端接到“123”后再往服务端发送“456”,结果服务端接收到的是“123”,再次发送“789”,服务端接收到的是“456”
2.当我从服务端往客户端发了个“123”,客户端接到“123”后再往服务端发送“4567”,结果服务端就报数组index超出范围了
想来想去都想不明白问题出在哪,百度、谷歌、StackOverFlow,都没有找到我要的答案,后来看到一篇文章问Socket的缓冲区为什么要用数组来接,突然灵光一现,也许问题就出在这个缓冲区上了,当我把数组分别定义成两个后,顺利解决问题了。
为啥怎么搜都搜不到这个问题呢,估计是没人跟我一样用同一个数组干过吧,汗。。。
具体的原理还没搞明白,等高手来回答。
记一次Socket编程踩的坑的更多相关文章
- Python网络编程踩的坑
错误:socket.error: [Errno 10013] 原因:端口号被占用 解决:换其他的端口号或者将其他应用的端口号关闭 错误:File "D:/pyworkspace/homewo ...
- 记Windows下初次使用dev C++进行socket编程过程
记初次接触socket编程,在devC++使用Winsock进行socket编程的一个过程,通过在devC++创建2个项目分别是server.client程序项目,感受通过socket使client与 ...
- 【爬坑】Python 3.6 在 Socket 编程时出现类型错误 TypeError: a bytes-like object is required, not 'str'
1. 问题描述 Python 3.6 在 Socket 编程时出现错误如下 Traceback (most recent call last): File "F:/share/IdeaPro ...
- 记一次:Windows的Socket编程学习和分析过程
Socket编程依赖于:WS2_32.dll --- 服务端 --- .导入我们需要的函数 #incldue <windows.h> //#include<WinSock2.h> ...
- Linux Socket编程
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- Linux Socket编程(不限Linux)【转】
转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几 ...
- C#版 Socket编程(最简单的Socket通信功能)
示例程序是同步套接字程序,功能很简单,只是客户端发给服务器一条信息,服务器向客户端返回一条信息:这里只是一个简单的示例,是一个最基本的socket编程流程,在接下来的文章中,会依次记录套接字的同步和异 ...
- PHP socket编程需要了解的一些基本知识
前面讲到了 fsockopen 的各种情况,其中涉及了很多其它知识,比如chunked分段传输,Keep-Alive,HTTP头字段等额外的知识,如果对这些知识一知半解,会影响对 PHP 的 sock ...
- SOCKet 编程 简介
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
随机推荐
- wadl 的自动生成(cxf版本2.7.6)
参考文档 http://cxf.apache.org/docs/jaxrs-services-description.html 获取项目 git@github.com:witaste/cxf-2.7. ...
- SIGPIPE导致cronttab和shell脚本等工作异常
cron和sh等可能被某些共享库hook,而这些共享库可能会触发SIGPIPE,导致crontab和shell工作异常,解决办法是程序忽略SIGPIPE或脚本中使用"trap '' SIGP ...
- 硬盘坏道检测工具对比(DiskGenius/HdTunePro/MHDD等)
说到硬盘检测软件,大家肯定会想到MHDD,但是MHDD真的好用?反正我觉得太难用了,只能在DOS下运行,不能在Win系统下运行:最重要的是只支持IDE硬盘模式,现在的主板几乎全部默认都是AHCI模式, ...
- (有点递归的感觉)RGCDQ--hdu--5317
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5317 感觉好神奇呀,一堆数在一起可以找到规律,学长讲完后,觉得自己是如此的so young f[x] ...
- HDU1072 Nightmare(BFS) 2016-07-24 14:02 40人阅读 评论(0) 收藏
Nightmare Problem Description Ignatius had a nightmare last night. He found himself in a labyrinth w ...
- android java层实现hook替换method
Android上的热修复框架 AndFix 大家都很熟悉了,它的原理实际上很简单: 方法替换——Java层的每一个方法在虚拟机实现里面都对应着一个ArtMethod的结构体,只要把原方法的结构体内容替 ...
- OpenGL常用的函数
OpenGL常用的函数 1. void glBegin(GLenummode) void glEnd(void) 参数说明: mode:创建图元的类型.可以是以下数值 GL_POINTS:把每一个顶点 ...
- C++ sort()函数的用法
C++sort()函数的用法 C++sort()函数的用法 近来看了c++标准库这本书,学到了很多,就把这其中的一点C++sort()函数的用法写下来和大家分享吧! (一)为什么要用c++标准库里的排 ...
- hdu 5024 最长的L型
http://acm.hdu.edu.cn/showproblem.php?pid=5024 找到一个最长的L型,L可以是斜着的 简单的模拟 #include <cstdio> #incl ...
- TFS支持移动设备,微软已经走出了第一步(手机上更新、查询工作项)
TFS支持移动设备,微软已经走出了第一步! 从现在开始,你可以在手机浏览器上打开自己的VSTS团队项目,会看大手机版的工作项界面,你可以在手机设备上更新.查询工作项. 这是原生自带的,这些移动功能马上 ...