闲来无事研究了下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编程踩的坑的更多相关文章

  1. Python网络编程踩的坑

    错误:socket.error: [Errno 10013] 原因:端口号被占用 解决:换其他的端口号或者将其他应用的端口号关闭 错误:File "D:/pyworkspace/homewo ...

  2. 记Windows下初次使用dev C++进行socket编程过程

    记初次接触socket编程,在devC++使用Winsock进行socket编程的一个过程,通过在devC++创建2个项目分别是server.client程序项目,感受通过socket使client与 ...

  3. 【爬坑】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 ...

  4. 记一次:Windows的Socket编程学习和分析过程

    Socket编程依赖于:WS2_32.dll --- 服务端 --- .导入我们需要的函数 #incldue <windows.h> //#include<WinSock2.h> ...

  5. Linux Socket编程

    “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...

  6. Linux Socket编程(不限Linux)【转】

    转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几 ...

  7. C#版 Socket编程(最简单的Socket通信功能)

    示例程序是同步套接字程序,功能很简单,只是客户端发给服务器一条信息,服务器向客户端返回一条信息:这里只是一个简单的示例,是一个最基本的socket编程流程,在接下来的文章中,会依次记录套接字的同步和异 ...

  8. PHP socket编程需要了解的一些基本知识

    前面讲到了 fsockopen 的各种情况,其中涉及了很多其它知识,比如chunked分段传输,Keep-Alive,HTTP头字段等额外的知识,如果对这些知识一知半解,会影响对 PHP 的 sock ...

  9. SOCKet 编程 简介

    “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...

随机推荐

  1. UVa 11491 Erasing and Winning (贪心,单调队列或暴力)

    题意:给一个数字(开头非0),拿掉其中的d个数字,使剩下的数字最大(前后顺序不能变). 析:拿掉d个数字,还剩下n-d个数字.相当于从n个数字中按先后顺序选出n-d个数字使组成的数字最大,当然采用窗口 ...

  2. cmake-add_definitions

    add_definitions: Adds -D define flags to the compilation of source files. add_definitions(-DFOO -DBA ...

  3. Codeforces807 C. Success Rate 2017-05-08 23:27 91人阅读 评论(0) 收藏

    C. Success Rate time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  4. 18、docker的持久化存储和数据共享

    18.1 Data Volume Docker持久化数据方案 基于本地文件系统的Volume   可以在执行docker create或者docker run的时候,通过-v参数将主机的目录作为容器的 ...

  5. 运行spark官方的graphx 示例 ComprehensiveExample.scala报错解决

    运行spark官方的graphx 示例 ComprehensiveExample.scala报错解决 在Idea中,直接运行ComprehensiveExample.scala,报需要指定master ...

  6. 【C#进阶】拥抱Lambda(一)

    写在开头,好奇从这里开始(当时让加查询条件,结果竟然是一句话来发挥神奇作用): this.TestGrade = CriteriaHelper.NewObject<ITestCase, DtoT ...

  7. js 利用数组实现类似于asp中的数据字典

    ---恢复内容开始--- 首先声明一个数组 var dictNew=new Array; var key; var value; for (var i = 0; i <50; i++) { // ...

  8. 附加属性来控制控件中,要扩展模块的visibility

    可解决: 文本框控件中的按钮,DataGridColumnHeader中加入Filter控件... cs文件中的 附加属性 + 样式文件中的 template+控件 -> visibility ...

  9. 基于Easyui框架的datagrid绑定数据,新增,修改,删除方法(四)

    @{ ViewBag.Title = "xxlist"; } <script type="text/javascript" language=" ...

  10. 实现单台测试机6万websocket长连接

    本文由作者郑银燕授权网易云社区发布. 本文是我在测试过程中的记录,实现了单台测试机发起最大的websocket长连接数.在一台测试机上,连接到一个远程服务时的本地端口是有限的.根据TCP/IP协议,由 ...