Socket通讯Client可以频繁连接Server端吗?

mcuatmel 2019-05-13 02:20:14
我用C#做了个程序,作Server 端,而客户端因现场需要与我是短连接,现象是:如果一秒内连续发10次连接并通讯可能只成功两三次或七八次,不知是什么原因,求指点!
具体过程是:客户端软件如果有触发条件就向我发一条指令(12个字节),先是连接我,然后发送,我收到后回复(12字节),他断开,我关闭对应线程。如果是慢发没问题,但如果是无延时的连续的重复上面的过程(做的假数据测试,现实情况和这个也差不多),那么就会随机的几次后他那边收不到的我回复数据的情况,而后他就进入超时,然后再继续。
...全文
625 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
mcuatmel 2019-05-24
  • 打赏
  • 举报
回复
@吹风的兔子,你若方便的话可不可以重现下你的测试代码?
@暗夜流岚,我这两天找时间测试下。我用抓包软件实在是找不出什么原因来。
吹风的兔子 2019-05-23
  • 打赏
  • 举报
回复
和Socket、交换机 都没有关系。应该是你的服务端代码没写好。 之前我测试过:Socket 连接、通讯、断开 每秒可以执行 500次以上。 一秒钟仅连接10次,断开率还这么高,即便是公网网络极差也不至于,何况局域网。
暗夜流岚 2019-05-23
  • 打赏
  • 举报
回复
你可以服务器Receive那里接收后直接控制台输出,然后返回信息;客户端那里接收到返回信息之后将Sockte清空,重新建立连接,用try catch打印一下看看有没哟捕获异常,这种重连很可能是套接字重复使用引发的异常
tsingherrhao 2019-05-22
  • 打赏
  • 举报
回复
可以连接的,但是服务器端一定要断开在指定时间内无法检测到的连接,不然反复连接,会造成服务端的处理压力
mcuatmel 2019-05-22
  • 打赏
  • 举报
回复
谢楼上各位!
服务器端发现有无效链接后都清掉了,基本不存在无效链接。
今天又通过抓包工具发现:一旦通讯中断,最后一次通讯是客户端发数据给服务端,服务端也收到了,但本应回一正常的数据,但却回了一包空数据帧,不知是什么原因,通过Tcp头的Flag区看仅是一个应答类型帧,没什么别的,而后过一会儿从服务端会发出十几个空帧,Flag区标识为rst=1,即链接重置,对刚才通讯过的端口要重置,不知为什么,那些已经关断了的。
wanghui0380 2019-05-20
  • 打赏
  • 举报
回复
这样的接收代码,看着挺郁闷,我不太想分析这个。 这样吧,把你的接收代码注销,只循环打印出收到的byte[],注意每收一次就直接打印,最后加打一个换行 其实,看到这个 while(true) ,sleep,buffer,if elseif,我大概能猜出来了,不过嘛这个东西还是你们解决一次印象才深刻 按照红字写的做,我相信你很快就能发现问题是什么了
mcuatmel 2019-05-20
  • 打赏
  • 举报
回复
谢楼上各位!
@生死看淡,不服就干,你说的这个库我没用过,不熟,有时间我研究下。
@datafansbj,你说的模式我不太懂,我的就是创建了一个Server,那它属于什么模式,我也不知道,我研究下。
我用抓包软件看了,每次服务端都把数据发出了,在客户端抓到了,但不知为什么,最后一包客户端好像是没收到,就一直在等一样,但实际上客户端的抓包软件都抓到了。
这个是Server端创建的代码:
/// <summary>
/// 启动服务
/// </summary>
/// <param name="port">端口号</param>
public bool OpenServer(int port)
{
try
{
Flag_Listen = true;
// 创建负责监听的套接字,注意其中的参数;
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建包含ip和端口号的网络节点对象;
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
try
{
// 将负责监听的套接字绑定到唯一的ip和端口上;
ServerSocket.Bind(endPoint);
}
catch
{
return false;
}
// 设置监听队列的长度;
ServerSocket.Listen(100);
// 创建负责监听的线程;
Thread Thread_ServerListen = new Thread(ListenConnecting);
Thread_ServerListen.IsBackground = true;
Thread_ServerListen.Start();

return true;
}
catch
{
return false;
}
}


这是客户端的测试代码:
// 接收消息线程
private void ReceiveMsg()
{
while (true)
{
//try
//{
// 创建并实例化用于存放数据的字节数组
byte[] getData = new byte[1024];
// 从网络数据流中读取数据
ns.Read(getData, 0, getData.Length);
if (getData.Length > 11)
{
if ((getData[0] == 0x46) && (getData[1] == 0x41) && (getData[10] == 0x46) && (getData[11] == 0x35))//验证通过
{
int cabnum = (getData[4] - 0x30) * 1000 + (getData[5] - 0x30) * 100 + (getData[6] - 0x30) * 10 + (getData[7] - 0x30);
byte[] tempary = { getData[4], getData[5], getData[6], getData[7] };
string strnum = System.Text.Encoding.Default.GetString(tempary);

if ((getData[2] == 0x38) && (getData[3] == 0x33))//83读状态
{
if (getData[8] == 0x30)
{
labST1.Invoke(showReceiveMsgCallBack, getData[9].ToString() + DISPINFO[getData[9] - 0x31]);
}
gbReceive = true;
gCmdItem++;
//breakConnect();
//消毁线程
receiveMsgThread.Abort();
}
else if ((getData[2] == 0x38) && (getData[3] == 0x32))//82设置状态
{
if (getData[8] == 0x30)
{
labST1.Invoke(showReceiveMsgCallBack, WRINFO[getData[9] - 0x30]);
}
gbReceive = true;
gCmdItem++;
//breakConnect();
//消毁线程
receiveMsgThread.Abort();
}
}
else
{
gbReceive = true;//在另一个线程中判断这个标志,如果为true,就先断开连接,再重新连接,再发命令。如下面代码
gCmdItem++;

}
}
Thread.Sleep(1);

}
}


等待的线程代码:
private void sentMsg()
{
while (true)
{
if (gbReceive)
{
breakConnect();
//Thread.Sleep(1);
if (gCmdItem < 10)
{
sentdata();//这个方法的代码如下:
}
gbReceive = false;
}
}
}
//发送数据的方法
private void sentdata()
{
switch (gCmdItem)
{
case 0:
if (String.IsNullOrEmpty(txtBoxState1.Text) == false)//不为空
{
creat_Connect();
string cmdstr = "FA"+gReadWrite+ txtBoxState1.Text + gCmdWord+"F5";
var strToBytes1 = System.Text.Encoding.UTF8.GetBytes(cmdstr);
// 将数据写入到网络数据流中
ns.Write(strToBytes1, 0, 12);
}
break;
case 1:
break;
....//共10个case
}
}

就这样,客户端一旦收到回复后就会断开,重连,发送下一个,直到10个发完。
m0_37646670 2019-05-18
  • 打赏
  • 举报
回复
假如你测试客户端就是粗暴的
while(true)
{
socket.send();
}
那服务器得处理得当才能布堵塞
datafansbj 2019-05-17
  • 打赏
  • 举报
回复
你的服务端是什么模式?普通线程模式和完成端口模式性能相差巨大,尤其是短连接比较频繁的时候,客户端会有很多连不上服务端的。
  • 打赏
  • 举报
回复
推荐你用fastsocket这个c#库,挺好用的。
  • 打赏
  • 举报
回复
你这种情况应该是代码有问题,1秒钟10次并发量又不是很大,应该是代码优化没做好。
mcuatmel 2019-05-17
  • 打赏
  • 举报
回复
谢楼上!请问这种短连接也会粘包吗?端口号不同的。
wanghui0380 2019-05-15
  • 打赏
  • 举报
回复
我这么多年的和无数人配合调试的情况 1.我自己这边不会处理粘包,我只取前12字节,后面扔掉了。表现就是发5次响应2次,甚至是只响应1一次(因为如果有校验规则,后面取的校验失败都不理会了) 2.对方不会处理粘包,我见过的情况。基本上的写法都是要么sleep,要么就给个大buffer,每次取完就不判定了,直接去buffer里的前12字节扔掉后面的,下次触发也好,sleep醒了也罢,一样的操作。 3.你这边处理不够及时,对方断开重来。(这个可以要求对方重试时候,别断开。或者规定加大超时时间判定)
wanghui0380 2019-05-15
  • 打赏
  • 举报
回复
引用 楼主 mcuatmel 的回复:
我用C#做了个程序,作Server 端,而客户端因现场需要与我是短连接,现象是:如果一秒内连续发10次连接并通讯可能只成功两三次或七八次,不知是什么原因,求指点! 具体过程是:客户端软件如果有触发条件就向我发一条指令(12个字节),先是连接我,然后发送,我收到后回复(12字节),他断开,我关闭对应线程。如果是慢发没问题,但如果是无延时的连续的重复上面的过程(做的假数据测试,现实情况和这个也差不多),那么就会随机的几次后他那边收不到的我回复数据的情况,而后他就进入超时,然后再继续。
我们不这么测,那些是看不见的。我即不相信他,也不相信你。我相信那些已经被无数人用的无数次的证明没有错的东西。 比如tcp模拟器,比如封包嗅探器。 你们只需要用这些工具一测就知道,到底他发了没。你到底回复没有 ps:凭经验来说,我认为是你们双方都有可能错误的处理了“粘包,分包”,当然我不会无端指责你们,所以我们说,用工具取证看对方到底发没发,每个包是不是真就你想的一个12字节。或者你发的不是他认为的12字节 我个人喜欢用wireshark这个工具看,这个玩意可能对新人来说不那么友好,不过用熟了还是挺喜欢。
mcuatmel 2019-05-15
  • 打赏
  • 举报
回复
楼上,这个只是极端测试,实际上也有可能发生,因为终端那边是随机的,所以没人会知道什么时候会有事件发生,有可能1个小时都没有,也有可能一起来多个触发。
大鱼> 2019-05-13
  • 打赏
  • 举报
回复
都那么频繁了还使用短连接,不明白为什么
  • 打赏
  • 举报
回复
这么平凡 还用啥端链接, 用长链接啊
mcuatmel 2019-05-13
  • 打赏
  • 举报
回复
我觉得是不是请求的太频了,被交换机给堵住了或是客户端的操作系统给限制了,不允许连接的太频了。
stherix 2019-05-13
  • 打赏
  • 举报
回复
这种应用场景就用UDP吧 虽然这个问题应该也是代码问题引起的
desperaso 2019-05-13
  • 打赏
  • 举报
回复
那就用websocket。
winform用的,非浏览器:
https://github.com/sta/websocket-sharp

110,536

社区成员

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

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

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