c#异步服务器应答



首先,如果存在这样的问题,我深表歉意,我在谷歌上搜索并阅读了可能有我的答案但找不到的问题。我有以下服务器代码:

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 + "rn" + "rn";
    }));
}

以及以下客户端代码:

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语法糖。

当涉及到使用流来回发送的字符串时,我使用StreamReaderStreamWriter,如下所示:

服务器端

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

最新更新