c#异步服务器应答
本文关键字:应答 服务器 异步 | 更新日期: 2023-09-27 18:29:05
首先,如果存在这样的问题,我深表歉意,我在谷歌上搜索并阅读了可能有我的答案但找不到的问题。我有以下服务器代码:
private void StartServer()
{
try
{
sSocket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
sSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
sSocket.Bind(new IPEndPoint(IPAddress.Any, 6666));
sSocket.Listen(0);
sSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Server", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void AcceptCallback(IAsyncResult ar)
{
try
{
cSocket = sSocket.EndAccept(ar);
buffer = new byte[cSocket.ReceiveBufferSize];
cSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
sSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Server", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
int received = cSocket.EndReceive(ar);
if(received == 0)
{
return;
}
Array.Resize(ref buffer, received);
text = Encoding.ASCII.GetString(buffer);
DisplayText(text);
cSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Server", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void DisplayText(string text)
{
Dispatcher.BeginInvoke(new Action(delegate
{
textBox.Text += ">> " + text + "'r'n" + "'r'n";
}));
}
以及以下客户端代码:
private void connect()
{
try
{
cSocket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
cSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
cSocket.BeginConnect(new IPEndPoint(IPAddress.Parse("192.168.1.2"), 6666), new AsyncCallback(ConnectCallback), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Registracija", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
cSocket.EndConnect(ar);
buffer = Encoding.ASCII.GetBytes("sendstuff");
cSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallBack), null);
}
catch (SocketException) { }
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Registracija", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void SendCallBack(IAsyncResult ar)
{
cSocket.EndSend(ar);
}
我知道我使用的是一个外部ip插座上的本地ip。我只是删除了一些不重要的东西,放了本地ip来隐藏外部ip。所以我将客户端连接到服务器,没有问题,一切都很好,我可以毫无问题地将数据发送到服务器,但我在任何地方都找不到如何让服务器回复客户端。举个例子,假设我向服务器发送一个字符串,说"我是一个字符串"。现在服务器用这个字符串做了一些事情,比如说切断"我是",现在它需要将剩下的"字符串"发送回客户端。
cSocket.BeginSend
在您呼叫DisplayText
的地方怎么样?显然,为了能够使用BeginSend
,您需要将文本放入缓冲区。有各种方法可以有效地做到这一点,但这超出了这个答案的范围。
但是如果您期望某种结构化数据,例如用换行符分隔的字符串,那么最好使用StreamReader.ReadLine
。如果结构更复杂,那么您将需要从缓冲区中自己进行解析。所以您需要从缓冲区中消耗一个字符,看看您是否有足够的数据,如果没有,请一直消耗到缓冲区为空。当缓冲区为空时,您需要通过调用BeginReceive
来再次填充它。当您有足够的数据要处理时,使用BeginSend
或流写入函数之一发回响应。
网络编程不是一件容易的事,你应该从互联网上查看一些示例服务器/客户端代码,并完全理解它们。最后但同样重要的是,我建议您使用wait/async语法糖。
当涉及到使用流来回发送的字符串时,我使用StreamReader
和StreamWriter
,如下所示:
服务器端
using (var reader = new StreamReader(theStream))
{
string message = reader.ReadLine();
// Or in an async method
string message = await reader.ReadLineAsync();
}
客户端
using (var writer = new StreamWriter(theStream))
{
writer.WriteLine(theMessage);
// Or in an async method
await writer.WriteLineAsync(theMessage);
}
注意:由于您使用的是TCP,因此可以使用new NetworkStream(theSocket)
从TCP套接字获取NetworkStream
。