2016-01-04 51 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