我是新来的异步套接字编程,我有我的异步函数的问题。TcpListener和TcpClient的异步函数问题,函数没有等待关键字
我正在尝试创建一个使用Windows窗体作为客户端和服务器的控制台应用程序的聊天程序。
这里是处理我的服务器上的连接代码:
public async void StartServer()
{
TcpListener listener = new TcpListener(_ip, _port);
listener.Start();
Console.WriteLine("Server is running on IP: {0} Port: {1}", _ip.ToString(), _port);
while (true)
{
try
{
TcpClient client = await listener.AcceptTcpClientAsync();
HandleConnections(client);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
private async void HandleConnections(TcpClient client)
{
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[256];
string message = null;
int x;
while(stream.DataAvailable)
{
x = await stream.ReadAsync(buffer, 0, buffer.Length);
message += Encoding.ASCII.GetString(buffer);
}
message = message.Replace('\0', ' ');
message = message.Trim();
Console.WriteLine("Message Recieved: " + message);
byte[] bytes = Encoding.ASCII.GetBytes(message);
await stream.WriteAsync(bytes, 0, bytes.Length);
stream.Close();
}
这里是连接到服务器的客户端程序代码:
private async void ConnectButton_Click(object sender, EventArgs e)
{
IPAddress address = IPAddress.Parse(IPInput.Text);
client = new TcpClient();
await client.ConnectAsync(address, 12345);
NetworkStream stream = client.GetStream();
string message = UsernameInput.Text + " Connected!";
Task<int> sendTask = SendMessage(stream, message);
int sendComp = await sendTask;
Task<string> recieveTask = RecieveMessage(stream);
string recieved = await recieveTask;
stream.Close();
ChatText.AppendText(recieved);
}
private async Task<int> SendMessage(NetworkStream stream, string message)
{
byte[] bytes = Encoding.ASCII.GetBytes(message + "\r\n");
await stream.WriteAsync(bytes, 0, bytes.Length);
return 1;
}
private async Task<string> RecieveMessage(NetworkStream stream)
{
byte[] buffer = new byte[256];
string message = null;
int x;
while (stream.DataAvailable)
{
x = await stream.ReadAsync(buffer, 0, buffer.Length);
message += Encoding.ASCII.GetString(buffer);
}
return message;
}
的第一个问题,我有是当我运行客户端程序并单击ConnectButton时,该消息被发送到输出Message Recieved: user Connected!
的服务器程序,但随后客户端程序在行ChatText.AppendText(recieved);
上遇到空引用异常,说recieved
变量为空。看起来线string recieved = await recieveTask;
没有等待任务完成执行,并且它跳到下一行,没有给recieved
赋值。如果我在private async Task<string> RecieveMessage(NetworkStream stream)
函数的顶部放置了一个断点并逐步完成,那么recieved
变量会得到它的值,并且代码将成功完成,但是没有断点,我会得到空引用异常。
我遇到的下一个问题是,如果我让服务器继续运行并再次打开客户端并尝试连接,服务器会在行message = message.Replace('\0', ' ');
上收到空引用异常。我第一次使用客户端运行时,服务器成功接收到消息,但是第二次,它没有从流中获取任何数据并将变量保留为null,从而导致空引用异常。
我很抱歉,如果我的代码是垃圾,我一直在阅读MSDN文档几个小时,我无法想出一个解决方案,我觉得我这样做是完全错误的。所以我的问题如下:
是什么导致我遇到这些错误?我以正确的方式处理这个问题吗?
哇,我没有想到像改变我的while循环一样简单的事情可以解决这个问题。非常感谢。我现在觉得有点愚蠢,因为我被这个问题困住了多久。 – PhantomWhiskers
@PhantomWhiskers - 一个单独的问题,它即将咬你 - 你真的*需要注意'ReadAsync'返回的*值。它会告诉你*已收到多少个字节。你的很多代码似乎都假定你会收到与你所要求的字节数完全一样多的字节,这并不能保证。请记住,TCP的抽象是一个字节流,而不是*消息*。如果你想发送和接收消息,那么你需要在TCP上实现它,或者转移到更高层次的抽象。 –