记一次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. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
随机推荐
- PAT甲 1007. Maximum Subsequence Sum (25) 2016-09-09 22:56 41人阅读 评论(0) 收藏
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- hdu 4982 贪心构造序列
http://acm.hdu.edu.cn/showproblem.php?pid=4982 给定n和k,求一个包含k个不相同正整数的集合,要求元素之和为n,并且其中k-1的元素的和为完全平方数 枚举 ...
- This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed(在64位模式下运行安装了32位的Oracle客户端组件时,会发生此问题)
部署win服务时出现下面的问题: 在事件查看器中看到如下错误: 日志名称: Application来源: ***调度服务日期: 2014/5/21 12:53:21事件 ID: 0任务类别: 无级别: ...
- Delphi 中 FindWindow 和 FindWindowEx 的语法和用法
FindWindow(lpClassName, {窗口的类名}lpWindowName: PChar {窗口的标题}): HWND; {返回窗口的句柄; 失败返 ...
- Delphi XE6 Android拨号函数
http://blog.sina.com.cn/s/blog_44fa172f0101rpex.html Delphi XE6 Android拨号函数 (2014-05-07 17:48:51) 转载 ...
- jenkins调用本地搭建sendmail邮件服务器发送邮件
应用jenkins发送邮件的邮件服务器 SMTP server 可以是本地的,也可以是远程,远程的就不多说了,在此说一下如何在jenkins本地服务器上搭建邮件服务器,并用jenkins发送邮件,详细 ...
- 排序算法之快速排序(Quicksort)解析
一.快速排序算法的优点,为什么称之为快排? Quicksort是对归并排序算法的优化,继承了归并排序的优点,同样应用了分治思想. 所谓的分治思想就是对一个问题“分而治之”,用分治思想来解决问题需要两个 ...
- C# AutoMapper 了解一下
什么是AutoMapper? 简单来说就是将一个对象映射到另一个对象的代码. 摆脱了繁琐的赋值过程 (最常见也就是Model -——ViewModel) AutoMapper安装 我使用的是VS201 ...
- 知识记录:ASP.NET 应用程序生命周期概述及Global.asax文件中的事件
IIS7 ASP.NET 应用程序生命周期概述 https://msdn.microsoft.com/zh-cn/library/bb470252(v=vs.100).aspx HttpApplica ...
- Reddit CEO亲自诠释内容审核的无奈
本文由 网易云发布. 导语:继数据泄露危机之后,Facebook将会雇用数千名新员工来负责新的验证系统,这个系统将首先在美国广告客户中生效,并将在未来几个月内涵盖其他国家.与此同时,如何让自己的社区 ...