gpt4 book ai didi

C# 异步套接字服务器接收问题

转载 作者:行者123 更新时间:2023-11-30 13:28:23 25 4
gpt4 key购买 nike

我已经在此处实现了关于这篇文章的服务器应用程序:http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c8781#Client1

总结:我正在使用 BeginAccept(..)、BeginReceive(..) 的异步套接字。我的服务器能够处理多个客户端,并且一切正常,直到客户端执行两个或多个同步发送操作而无需等待一段时间。客户端没有收到任何错误,因此没有通知服务器没有收到第二条消息!如果客户等待大约。第一次发送操作后 100 毫秒,一切正常。我认为当我使用 TCP 时我可以确保服务器收到消息。 (除了抛出异常)!你能给我一个解决这个问题的方法吗?

这是我在服务器中实现的 WaitForData(..) 和 OnDataReceive(..) 方法

public void WaitForData(MyClient client)
{
try
{
if (pfnCallBack == null)
{
pfnCallBack = new AsyncCallback(OnDataReceived);
}

iarResult = client.Socket.BeginReceive(client.DataBuffer,
0, client.DataBuffer.Length,
SocketFlags.None,
pfnCallBack,
client);
}
catch (SocketException se)
{
MessageBox.Show("SocketException@WaitForData" + se.Message);
}
}
public void OnDataReceived(IAsyncResult asyn)
{
try
{
MyClient user= (MyClient)asyn.AsyncState;
int iRx = user.Socket.EndReceive(asyn);

byte[] receivedData = user.DataBuffer;

MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(receivedData, 0, receivedData.Length);
memStream.Seek(0, SeekOrigin.Begin);
MyMessage msg = (MyMessage)binForm.Deserialize(memStream);

switch (msg.Command)
{
case (MyMessage.MyCommand.ConnId):
this.connId = (int) msg.MyObject;
tsslConnStatus.Text += " | ID: " + connId.ToString();
break;

case (MyMessage.MyCommand.Text):
MessageBox.Show(msg.MyObject.ToString());
break;
}
WaitForData(server);
}
catch (ObjectDisposedException ode)
{
MessageBox.Show("ObjectDisposedException@OnReceiveData" + ode.Message);
}
catch (SocketException se)
{
MessageBox.Show("SocketException@OnReceiveData" + se.Message);
}
}

客户端调用同步发送方法两次或更多次!服务器 INSTANCEOF MyClient

if (server.Socket.Connected)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, message);
MyMessage = new MyMessage(something);
server.Socket.Send(ms.ToArray());
}

所以,我认为这段代码片段一定足以让您了解我正在尝试使用的想法!如果您需要更多详细信息或代码片段,请告诉我我会发布!

谢谢!

最佳答案

TCP 是基于流的,而不是基于消息的。一个 Read 可以包含以下任何备选方案:

  • 信息的一小部分
  • 一半的信息
  • 只有一条消息
  • 一条半信息
  • 两条消息

因此您需要使用某种方法来查看是否收到了完整的消息。最常见的方法是:

  • 添加一个页脚(例如一个空行)来指示消息的结尾
  • 添加包含消息长度的固定长度 header

更新

仅将长度作为标题的简单示例。

服务器端:

var buffer = binaryFormmater.Serialize(myobj);
var length = buffer.Length;
networkStream.Send(length);
networkStream.Send(buffer, 0, buffer.Length);

客户端:

var header = new buffer[4];
// TODO: You need to make sure that 4 bytes have been read.
networkStream.Read(header, 0, 4);
var length = BitConverter.ToInt32(buffer);

var readbuffer= new byte[65535];
var bytesLeft = length;
var messageStream = new MemoryStream();
while (bytesLeft > 0)
{
var read = networkStream.Read(readbuffer, 0, bytesLeft);
messageStream.Write(readbuffer, 0, read);
bytesLeft -= read,
}

messageStream.Seek(0, SeekOrigin.Begin);
MyMessage msg = (MyMessage)binForm.Deserialize(messageStream);

关于C# 异步套接字服务器接收问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5934469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com