关于SOCKET通讯顺序

那该多好啊!!! 2018-11-28 10:25:05
关于SOCKET异步通讯的顺序,当连接好服务器端,客户端是先发送还是先接收呢?
我在看资料时,看到有人是这样处理的,但我始终感觉不太对,
先是用BeginConnect连接好服务器,
然后把接收和发送放在一个while循环里,在这个循环里
先用BeginReceive(tObject.buffer, 0, 128, SocketFlags.Peek, new AsyncCallback(this.ReceiveCallback), tObject)来接收数据
这里就疑惑了,我以前写同步通讯时,要先Send 才能receive数据。这里就直接来BeginReceive,那缓存里的数据是怎么有的?
最后才执行,BeginSend,

...全文
334 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wc19840730 2018-11-29
  • 打赏
  • 举报
回复
正好准备也要有SOCKET方面的业务,学习一下各种知识~~~
  • 打赏
  • 举报
回复
引用 1 楼 以专业开发人员为伍 的回复:
在 ReceiveCallback 过程中,当接收到一部分数据时,才会使用另一个 BeginReceive 来注册下一个 ReceiveCallback 操作。用什么 while 循环啊?你是在哪里看到的写循环语句的代码的?


同步通信不是先send然后在receive吗,发送和接收都 先存到缓存里,
  • 打赏
  • 举报
回复
Try

Do While (True)

strTemp = ""

gCommuWithNetPLC_Thread(index) = True

If gSysState = SystemState.SysExit Then
Exit Do
End If

If gConnPLCSck(index).ReceivingFlag = False Then
Call gConNetPLC(index).Receive(gConnPLCSck(index))
End If

If UCase(strReceive) = "ERRCLOSE" Or gConnPLCSck(index).currSocket.Connected = False Then ' gWeldSck.CommState <> enCommState.Connected Then
gCommuWithNetPLC_Thread(index) = False
gConnPLCSck(index).CommState = enCommState.Broken
'gWeldSck.CommState=
Exit Do
End If
'------------------------------

If gConNetPLC(index).ReceiveString <> "" Then

'PLC返回值
gPlcReturnBuff = gConNetPLC(index).ReceiveByteValue() '//5555555555555555555555555555

strReceive = gConNetPLC(index).ReceiveString '接收信息
gConNetPLC(index).ReceiveString = "" '将接收信息置空

End If

If InStr(1, strReceive, vbCrLf) > 0 Then ' strReceive <> "" Or
strTemp = UCase(Replace(strReceive, vbCrLf, ""))
strReceive = ""
ElseIf InStr(1, strReceive, vbCr) > 0 Then
strTemp = UCase(Replace(strReceive, vbCr, ""))
strReceive = ""
Else
If strReceive <> "" Then
strTemp = UCase(strReceive)
End If
End If

If gBlnSendCommand = True And gSendToPLCCommand.Length > BYTE_MIN_LEN Then

gConNetPLC(portIdx).Send(gConnPLCSck(portIdx).currSocket, gSendToPLCCommand)

ReDim gSendToPLCCommand(0)
gBlnSendCommand = False
End If


'分析收到的字符
If strTemp <> "" Then
myData = Split(strTemp, ":")




End If

Threading.Thread.Sleep(5)

Loop

gCommuWithNetPLC_Thread(index) = False

If (gPromptInfo = "") Then
gPromptInfo = System.DateTime.Now + "-->与[网络PLC:" & index & "]通讯线程中断退出,重新启动连结线程..."
Else
gPromptInfo = gPromptInfo + System.Environment.NewLine + System.DateTime.Now + "-->与[网络PLC:" & index & "]通讯线程中断退出,重新启动连结线程..."
End If

'连接[主机:自动焊设备]
blnFlag = NetPlcClient_Init(index)

System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf Build_ConnNetPLCTask), index)
System.Threading.Thread.Sleep(50)

Catch ex As Exception

gCommuWithNetPLC_Thread(index) = False

If (gPromptInfo = "") Then
gPromptInfo = System.DateTime.Now + "-->与[网络PLC:" & index & "]通讯线程异常:" & ex.Message
Else
gPromptInfo = gPromptInfo + System.Environment.NewLine + System.DateTime.Now + "-->与[网络PLC:" & index & "]通讯线程异常:" & ex.Message
End If

blnFlag = NetPlcClient_Init(index)
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf Build_ConnNetPLCTask), index)
System.Threading.Thread.Sleep(50)

End Try
  • 打赏
  • 举报
回复
用一个while循环,检测到缓存里有数据,而且确定数据大于多少就接收数据。当要发送数据时,就发送。一直这样循环下去,
我觉得他这样方式很好,只是我还没有完全看懂,
  • 打赏
  • 举报
回复
仅仅对于短链接,并且是客户端,仅仅对于这种一场简单的编程情形,并且我们不过是只会半分钟时间来“玩一玩儿 demo 代码”(而并不是要设计一个通用网关代理封装 api),才会用
client.Send(data);
do
{
    var x = client.Receive();
    buffer.Add(x);
}while(判断还没有收到一个完整的消息结束标记);
解析buffer中的数据;
client.Close();
    
这类思路来写代码。 tcp 协议中,接收数据是粘包/分包的,这是最起码的知识。并且只有客户端短链接,才可以不管不顾地认为仅仅是“一问一答然后就关闭连接”的模式。 对于长连接,比如说客户端以顺序1、2、3、4、5的次序(顺序或者并发)执行了多个 Send 操作,服务器端并发进行命令处理,完全可能以 3、2、1、5、4的顺序返回结果。然后客户端应该根据收到消息的顺序,来触发必要的事件/委托,通知之前 Send 消息的任务开始处理委托回调。 说多了你也不一定理解。只要记住几点基本知识,tcp 通讯每一条消息通讯必定是有粘包/分包的,长连接处理必定是并发多线程随即顺序的,通讯连接建立之后必定会随时接受到对方推送来的任意消息。基于这些现实概念来学习,才真正能判断什么是真的知识。
  • 打赏
  • 举报
回复
当通讯握手之后,任何时候都可能随时收到数据。你“以前”就没有学过通讯程序设计,可能只是看过一些简单的介绍个别语句的demo。类似 msdn 上的关于个别语句的 demo,是 msdn 中最垃圾的代码。msdn 中关于 socet 等基础通讯的代码都非常垃圾,基本上都不是大程序该有的设计思路。但是作为介绍个别语句的文档,自然是针对什么都不懂的初学者,写出那种毫无实用系统设计模式的非常简单、仅适合初学者的代码也是可以理解的。
  • 打赏
  • 举报
回复
在 ReceiveCallback 过程中,当接收到一部分数据时,才会使用另一个 BeginReceive 来注册下一个 ReceiveCallback 操作。用什么 while 循环啊?你是在哪里看到的写循环语句的代码的?

110,570

社区成员

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

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

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