2016-01-04 44 views
0

首先我做道歉,如果这样的问题存在,我搜索谷歌和通过可能有我的答案但找不到它的问题。 我有以下的服务器代码: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 + "\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隐藏外部的一个。因此,我将客户端连接到服务器,没有问题,一切都很好,我可以毫无问题地将数据发送到服务器,但我无法弄清楚/找到任何地方如何让服务器向客户端回复一些东西。举个例子,假设我发送一个字符串给服务器,说“我是一个字符串”。现在,服务器用这个字符串做了一些事情,比方说,切断“我是”,现在需要将剩下的“字符串”发送回客户端。

回答

0

cSocket.BeginSend怎么样在你拨打DisplayText的地方?很显然,要使用BeginSend,您需要将文本放入缓冲区。有效地做到这一点有很多种方式,但它不在这个答案的范围之内。

但是如果您期待某种类型的结构化数据(如用换行符分隔的字符串),那么最好使用StreamReader.ReadLine。如果结构更复杂,那么您需要从缓冲区中解析自己。所以你需要从缓冲区中消耗一个字符,看看你是否有足够的数据,如果没有保持消耗,直到缓冲区为空。当缓冲区为空时,您需要通过调用BeginReceive来重新填充缓冲区。当您有足够的数据进行处理时,请使用BeginSend或其中一种流写入功能发回响应。网络编程不是一件容易的事情,你应该从互联网上查看一些示例服务器/客户端代码并彻底理解它们。最后但并非最不重要的,我建议你使用await/async语法糖。

+0

正在发送的字符串非常简单,所以缓冲区在我的情况下工作正常。事情是,如果我BeginSend我打电话显示文本如何将客户端接收它,因为没有ReceiveCallbacks等? – snorkle213

+0

显然你需要使用'BeginReceive'并在你发送数据之前在你的客户端注册你的回调函数,即在'ConnectCallback'函数中。事情是,可以在另一侧的单个“接收”回调中接收多个“发送”,反之亦然。因为你正在处理流,所以要小心。这就是为什么如果您想要多次处理数据,您需要分隔符/结构化数据,例如从多个句子中删除“我”。 – mostruash

0

当谈到来回发送使用流串,我使用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