Code Bye

C#SOCKET长连接小数据程序未响应

最近由于业务的需要,Linux系统嵌入式设备往我做的服务程序发送数据。
速度奇慢,而且还是程序无响应。后来自己用C#写了一个客户端用来测试。已经用了线程池,不知道用法对不对。请大家帮忙看下。

服务端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace consoleSocketServer
{
    class Program
    {
        static int socketCount = 0;
        static Socket serverSocket;
        static Socket clientSocket;
        public static int clientcount = 0;
        public int clientnum = 0;
        static int listSQL = 0;
        static bool asy = true;
        public static Int32 portServer = 0;
        public static string ipServer = “”;
        public static Thread threadSocketListen;
        public static Thread threadDoWork;
        public static Thread threadInsert;
        public static int countsql = 0;
        static void Main(string[] args)
        {
            IPAddress ipAddress;
            portServer = 4660;
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            ipAddress = IPAddress.Parse(“192.168.33.29”);
            ipServer = ipAddress.ToString();

            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);

            Console.WriteLine(“服务器IP:” + ipServer + ”  端口:” + portServer);
            serverSocket.Bind(localEndPoint);
            serverSocket.Listen(20);
            //设置线程池
            ThreadPool.SetMaxThreads(4, 4);
            //开启新的线程监听
            threadSocketListen = new Thread(SocketListen);
            threadSocketListen.Start();

            Console.WriteLine(“服务启动成功”);
        }

        static void SocketListen()
        {
            while (true)
            {

                //接受客户端信息
                clientSocket = serverSocket.Accept();
                //开启处理线程
                ThreadPool.QueueUserWorkItem(new WaitCallback(doWork));

                //threadDoWork = new Thread(new ThreadStart(doWork));
                //threadDoWork.Start();

            }
        }
        /// <summary>
        /// 处理方法
        /// </summary>
        static void doWork(object a)
        {

            //获取客户端信息 
            IPEndPoint ipEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
            string address = ipEndPoint.Address.ToString();
            //Console.WriteLine(address + “:连接成功”);

            //取消息
            byte[] inBuffer = new byte[1024];
            byte[] outBuffer = new byte[8];
            string inBufferStr = “”;
            int rec = 0;
            StringBuilder sb = new StringBuilder();
            while (true)
            {
                try
                {
                    rec = clientSocket.Receive(inBuffer);//如果没有消息为空 阻塞 当前循环 
                    //收到的长度不够 忽略此次数据
                    if (rec <= 8)
                    {
                        continue;
                    }

                    int ll = inBuffer[4] + inBuffer[5] * 255;

                    inBufferStr = Encoding.UTF8.GetString(inBuffer, 8, ll);

                    Console.WriteLine(inBufferStr);

                    //回复收到 
                    outBuffer[4] = 0;
                    outBuffer[5] = 0;
                    outBuffer[6] = 0;
                    outBuffer[7] = 0;
                    outBuffer[3] = 0;
                    outBuffer[2] = 0;
                    outBuffer[1] = 0;
                    outBuffer[0] = 1;

                    clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
                    socketCount++;
                    Console.WriteLine(socketCount.ToString());
                    //break;
                }
                catch (SocketException es)
                {
                    //clientSocket.Close();
                    return;
                }

            }

        }
    }
}

客户端:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace SocketClient
{
    class Program
    {
        static Socket clientSocket;
        static void Main(string[] args)
        {
            try
            {
                //将网络端点表示为IP地址和端口 用于socket侦听时绑定 
                IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(“192.168.33.29”), 4660);

                clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                //将Socket连接到服务器 
                clientSocket.Connect(ipep);

                string outBufferStr;
                //发送消息 
                outBufferStr = “123456789qwe|789654123|1|2015-04-22 10:51:34|6|test1|test2| “;
                byte[] tempb = Encoding.UTF8.GetBytes(outBufferStr);

                byte[] outBuffer = new byte[tempb.Length + 8];

                //加功能和长度
                outBuffer[0] = 1;
                outBuffer[1] = 0;
                outBuffer[2] = 0;
                outBuffer[3] = 0;
                outBuffer[4] = Convert.ToByte(tempb.Length % 255);
                outBuffer[5] = Convert.ToByte(tempb.Length / 255);
                outBuffer[6] = 0;
                outBuffer[7] = 0;

                for (int i = 0; i < tempb.Length; i++)
                {
                    outBuffer[8 + i] = tempb[i];
                }

                // Byte[] inBuffer = new Byte[1024];

                int kkk = 0;
                while (kkk <= 10000)
                {

                    clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
                    kkk++;
                    Thread.Sleep(1);
                    Console.WriteLine(kkk.ToString());
                    //Console.WriteLine(“服务器响应:”);
                    //接收服务器端信息 
                    //clientSocket.Receive(inBuffer, 1024, SocketFlags.None);
                    //Console.WriteLine(Encoding.ASCII.GetString(inBuffer));
                }
                Console.WriteLine(kkk.ToString());
                Console.ReadLine();
            }
            catch (Exception exp)
            {
                Console.WriteLine(exp.Message);
                Console.ReadLine();

            }
        }

    }
}

1分
   //收到的长度不够 忽略此次数据
                    if (rec <= 8)
                     {
                         continue;
                     }

那有这么写的?长度不够也是数据啊,那能随便就不要了呢 

引用 1 楼 rtdb 的回复:
   //收到的长度不够 忽略此次数据
                    if (rec <= 8)
                     {
                         continue;
                     }

那有这么写的?长度不够也是数据啊,那能随便就不要了呢 

协议部分实际上是包含了,功能码,长度,校验这些。现在测试很忙就把数据校验去掉了。socket做得少。不知道会不会丢包。串口会经常丢包。而且监控数据少一次没关系的。主要是根据软件的用途吧。我也希望。。。一点都不丢失

5分
Console.WriteLine(“服务启动成功”);
之后
要加上
Console.ReadLine();

否则程序运行完了不退出了

5分
还有,
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
应该写成
IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer);

你指定了一个IP,只侦听这个IP来的数据
那么其他IP来的数据当然不响应

5分
还有既然是短连接,你recieve的时候要加ReadTimeOut啊
超时了赶紧进catch
否则某个客户端连接了但是不发送数据,你接收线程不永远阻塞住?

如果你想多客户端能够同时连接,要给每个子线程new一个socket对象(TCPClint)来接收不同客户端发送的数据
都用同一个Socket,数据不会错乱吗

总之你这代码问题很多,先解决了这几个问题,再有新的问题再想办法解决吧

引用 3 楼 Z65443344 的回复:

Console.WriteLine(“服务启动成功”);
之后
要加上
Console.ReadLine();

否则程序运行完了不退出了

高人啊!一眼看出这么多问题。没错是无法完全退出,这其实也是一部分。因为所有的服务端已经超过500行代码太复杂了只是抽取了问题点的部分。
Process.GetCurrentProcess().Kill();   //完全退出进程

引用 4 楼 Z65443344 的回复:

还有,
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer);
应该写成
IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer);

你指定了一个IP,只侦听这个IP来的数据
那么其他IP来的数据当然不响应

不用那样写,也可以接受其他IP过来的信息呀。我这个是服务端。客户端  很多,客户端都是往这个IP这个端口丢数据就好了。

引用 5 楼 Z65443344 的回复:

还有既然是短连接,你recieve的时候要加ReadTimeOut啊
超时了赶紧进catch
否则某个客户端连接了但是不发送数据,你接收线程不永远阻塞住?

如果你想多客户端能够同时连接,要给每个子线程new一个socket对象(TCPClint)来接收不同客户端发送的数据
都用同一个Socket,数据不会错乱吗

总之你这代码问题很多,先解决了这几个问题,再有新的问题再想办法解决吧

超时部分,后来我加了。效果还是一样。目前解决的好像七七八八。解决的方法是在客户端处理的。
加入收到接受成功了在进行第二次的发送。

int kkk = 0;
                while (kkk < 500000)
                {
                    clientSocket = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                    clientSocket.Connect(ipep);
                    clientSocket.Send(outBuffer, outBuffer.Length, SocketFlags.None);
                    kkk++;
                    Thread.Sleep(100);
                    Console.WriteLine(kkk.ToString());

                    //Console.WriteLine(“服务器响应:”);
                //接收服务器端信息 
               
                    clientSocket.Receive(inBuffer, 8, SocketFlags.None);
                    if (inBuffer[0] == 1)
                    {
                        clientSocket.Close();
                        continue;
                    }
                    else
                    {
                        break;
                    }
                    //Console.WriteLine(Encoding.ASCII.GetString(inBuffer));
                   
                }

另外你说的 对象问题,也就是我头疼的问题。我用了一个字典来保存KEY IP  VALUE  SOCKET 对象。却发现短连接速度太快了。这个IP还在字典里面还没有进行完 DOWORK的流程  没有正常释放字典数据。又试着添加  字典已经存在的KEY  会报错。才写成目前这样。

所以关于回复给哪个IP地址的问题也还没解决。我测过3个客户端一起启动。服务端就很容易崩了。  求大神继续支招。

23分
1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。
起步也得用select吧
2. 异步模式比同步模式性能要好些
3..net的SocketAsyncEventArgs足够强大了,为何不用呢
1分
至少有一个完全错误的严重问题,你的 clientSocket  应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。
引用 9 楼 xian_wwq 的回复:

1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。
起步也得用select吧
2. 异步模式比同步模式性能要好些
3..net的SocketAsyncEventArgs足够强大了,为何不用呢

SocketAsyncEventArgs 在CSDN下载了一个。测试了一下,稳定性是不错。但是CPU 不忍直视啊….   I7的CPU 一个客户端不延迟的发送居然能用到百分之百。

请大神给一个简单基础的案列最好的中文的…英文还在脑补

引用 10 楼 sp1234 的回复:

至少有一个完全错误的严重问题,你的 clientSocket  应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。

谢谢提醒,这个问题已经回复3L了。

详细看8L

后来的解决方式比较蛋疼吧。短连接改成长连接了。   因为50W的数据量 就要连接 与断开50W次   后来长连接解决这个问题。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C#SOCKET长连接小数据程序未响应