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

vbandplc 2015-04-22 09:53:45
最近由于业务的需要,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();

}
}

}
}
...全文
356 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
vbandplc 2015-04-24
  • 打赏
  • 举报
回复
后来的解决方式比较蛋疼吧。短连接改成长连接了。 因为50W的数据量 就要连接 与断开50W次 后来长连接解决这个问题。
vbandplc 2015-04-23
  • 打赏
  • 举报
回复
引用 10 楼 sp1234 的回复:
至少有一个完全错误的严重问题,你的 clientSocket 应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。
谢谢提醒,这个问题已经回复3L了。 详细看8L
vbandplc 2015-04-23
  • 打赏
  • 举报
回复
引用 9 楼 xian_wwq 的回复:
1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。 起步也得用select吧 2. 异步模式比同步模式性能要好些 3..net的SocketAsyncEventArgs足够强大了,为何不用呢
SocketAsyncEventArgs 在CSDN下载了一个。测试了一下,稳定性是不错。但是CPU 不忍直视啊.... I7的CPU 一个客户端不延迟的发送居然能用到百分之百。 请大神给一个简单基础的案列最好的中文的...英文还在脑补
  • 打赏
  • 举报
回复
至少有一个完全错误的严重问题,你的 clientSocket 应该是方法内的“局部”变量,决不能是全局共享的。否则就彻底乱了套了。
xian_wwq 2015-04-23
  • 打赏
  • 举报
回复
1. 一个客户端起一个线程的模式只能支持少量客户端,程序没有可扩展性。 起步也得用select吧 2. 异步模式比同步模式性能要好些 3..net的SocketAsyncEventArgs足够强大了,为何不用呢
rtdb 2015-04-22
  • 打赏
  • 举报
回复

   //收到的长度不够 忽略此次数据
                    if (rec <= 8)
                     {
                         continue;
                     }
那有这么写的?长度不够也是数据啊,那能随便就不要了呢
vbandplc 2015-04-22
  • 打赏
  • 举报
回复
引用 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个客户端一起启动。服务端就很容易崩了。 求大神继续支招。
vbandplc 2015-04-22
  • 打赏
  • 举报
回复
引用 4 楼 Z65443344 的回复:
还有, IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer); 应该写成 IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer); 你指定了一个IP,只侦听这个IP来的数据 那么其他IP来的数据当然不响应
不用那样写,也可以接受其他IP过来的信息呀。我这个是服务端。客户端 很多,客户端都是往这个IP这个端口丢数据就好了。
vbandplc 2015-04-22
  • 打赏
  • 举报
回复
引用 3 楼 Z65443344 的回复:
Console.WriteLine("服务启动成功"); 之后 要加上 Console.ReadLine(); 啊 否则程序运行完了不退出了
高人啊!!一眼看出这么多问题。没错是无法完全退出,这其实也是一部分。因为所有的服务端已经超过500行代码太复杂了只是抽取了问题点的部分。 Process.GetCurrentProcess().Kill(); //完全退出进程
於黾 2015-04-22
  • 打赏
  • 举报
回复
还有既然是短连接,你recieve的时候要加ReadTimeOut啊 超时了赶紧进catch 否则某个客户端连接了但是不发送数据,你接收线程不永远阻塞住? 如果你想多客户端能够同时连接,要给每个子线程new一个socket对象(TCPClint)来接收不同客户端发送的数据 都用同一个Socket,数据不会错乱吗 总之你这代码问题很多,先解决了这几个问题,再有新的问题再想办法解决吧
於黾 2015-04-22
  • 打赏
  • 举报
回复
还有, IPEndPoint localEndPoint = new IPEndPoint(ipAddress, portServer); 应该写成 IPEndPoint localEndPoint = new IPEndPoint(IpAddress.Any, portServer); 你指定了一个IP,只侦听这个IP来的数据 那么其他IP来的数据当然不响应
於黾 2015-04-22
  • 打赏
  • 举报
回复
Console.WriteLine("服务启动成功"); 之后 要加上 Console.ReadLine(); 啊 否则程序运行完了不退出了
vbandplc 2015-04-22
  • 打赏
  • 举报
回复
引用 1 楼 rtdb 的回复:

   //收到的长度不够 忽略此次数据
                    if (rec <= 8)
                     {
                         continue;
                     }
那有这么写的?长度不够也是数据啊,那能随便就不要了呢
协议部分实际上是包含了,功能码,长度,校验这些。现在测试很忙就把数据校验去掉了。socket做得少。不知道会不会丢包。串口会经常丢包。而且监控数据少一次没关系的。主要是根据软件的用途吧。我也希望。。。一点都不丢失

111,105

社区成员

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

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

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