gpt4 book ai didi

c# - 尝试创建异步 tcp 服务器

转载 作者:太空宇宙 更新时间:2023-11-03 13:28:38 24 4
gpt4 key购买 nike

我正在尝试学习如何在 C# 中创建异步 tcp 服务器,但我的代码遇到了一个小问题。

I tried to modify this code

这就是我所做的:

public class ClientContext 
{
public TcpClient client { get; set; }
public NetworkStream stream { get; set; }
public byte[] buffer { get; set; }
public string message { get; set; }
// public MemoryStream message = new MemoryStream ();

public ClientContext ()
{
buffer = new byte[14];
message = "";
}
}

public class TCPServer
{

public TCPServer ()
{
// Setup the server side
TcpListener listener = new TcpListener (new IPEndPoint (IPAddress.Parse("127.0.0.1"), 14000));
listener.Start ();
// Server side ok, wait for client to connect
listener.BeginAcceptTcpClient (OnClientAccepted, listener);

Console.WriteLine ("Press enter to exit...");
Console.ReadLine ();
listener.Stop ();
}

private void OnClientAccepted (IAsyncResult ar)
{
// A client connected
TcpListener listener = (TcpListener)ar.AsyncState;

if (listener == null)
return;

try {
// Create a new client context to store connection infos about dat client
ClientContext context = new ClientContext ();
context.client = listener.EndAcceptTcpClient (ar);
context.stream = context.client.GetStream ();
// The client is now ready, read what it has to say
context.stream.BeginRead (context.buffer, 0, context.buffer.Length, OnClientRead, context);
} finally {
listener.BeginAcceptTcpClient (OnClientAccepted, listener);
}
}

private void OnClientRead (IAsyncResult ar)
{
// The client wants to say something
ClientContext context = (ClientContext)ar.AsyncState;
context.message = "";

if (context == null)
return;

try {
// Read what it says
if(context.stream.CanRead) {

do {

context.stream.Read (context.buffer, 0, context.buffer.Length);
context.message += Encoding.ASCII.GetString (context.buffer);
//length -= context.message.Length;

} while (context.stream.DataAvailable); // && length < readBuffer.Length

OnMessageReceived(context);
}

} catch (Exception) {
context.client.Close ();
context.stream.Close ();
context = null;
} finally {
// If we are still connected to the client, read what it has to say...
if (context != null)
context.stream.BeginRead (context.buffer, 0, context.buffer.Length, OnClientRead, context);
}

}

private void OnMessageReceived (ClientContext context)
{
// Display what the client said
Console.WriteLine ("Message reçue : " + context.message);
}
}

问题是:我有一个客户端发送了 50 个“hello world !!”向服务器发送消息,服务器仅打印 25/26 “hello world !!”在控制台中。我已经使用 SocketSniff 查看了套接字,我看到服务器套接字收到了 50 个“hello world !!”,所以我的代码肯定有什么地方失败了,但是什么?

你们有什么想法吗?

最佳答案

context.stream.Read (context.buffer, 0, context.buffer.Length);
context.message += Encoding.ASCII.GetString (context.buffer);

这里您没有检查 Stream.Read 的返回值. Read 可以将单个字节放入缓冲区,但您随后要解码整个 缓冲区,其中包含之前 Read 调用的剩余字节。这必须是:

int bytesRead = context.stream.Read (context.buffer, 0, context.buffer.Length);
context.message += Encoding.ASCII.GetString (context.buffer, 0, bytesRead);

但是你遇到的问题是不同的。你正在做一个危险的同步和异步混合......不稳定的结果。 您不应在 BeginRead 回调中发出同步读取!您必须调用 EndRead:

int bytesRead = context.stream.EndRead(ar);
context.message += Encoding.ASCII.GetString (context.buffer, 0, bytesRead);
OnMessageReceived(context);
context.stream.BeginRead (context.buffer, 0, context.buffer.Length, OnClientRead, context);

无需检查 DataAvailableCanRead

关于c# - 尝试创建异步 tcp 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21430489/

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