2013-07-10 120 views
0

我有一個使用tcp套接字發送和接收消息的客戶端。 他們給了我們一個目的地IP和端口。爲了得到這個感覺,我開始了一個小的控制檯應用程序,客戶端和服務器。我用我的IP和端口。啓動服務器。然後通過客戶端發送一些字符串。我能夠在服務器控制檯上看到它。 該程序僅建立單向連接客戶端 - >服務器。 我該如何實現雙向? 我需要實現一個tcp偵聽器嗎?套接字和收聽者

Server: 
static void Main(string[] args) 
     { 
      sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234); 
      sck.Bind(localEndpoint); 
      sck.Listen(100); 

      Socket accepted = sck.Accept(); 
      Buffer = new byte[accepted.SendBufferSize]; 
      int bytesRead = accepted.Receive(Buffer); 
      byte[] formatted = new byte[bytesRead]; 
      for (int i = 0; i < bytesRead; i++) 
      { 
       formatted[i] = Buffer[i]; 
      } 
      string strData = Encoding.ASCII.GetString(formatted); 
      Console.WriteLine(strData); 
      Console.Read(); 
      sck.Close(); 
      accepted.Close(); 



     } 
Client: 
static void Main(string[] args) 
     { 
      sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234); 
     // IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("68.109.249.167"), 35520); 
      try 
      { 
       sck.Connect(localEndpoint); 

      } 
      catch(Exception ex) 
      { 
       Console.Write("unable to connect to remote endpoint"); 
       Main(args); 
      } 
      Console.Write("Enter Text"); 
       string text=Console.ReadLine(); 
      byte[] data= Encoding.ASCII.GetBytes(text); 

      sck.Send(data); 
      Console.Write("Data Sent!\r\n"); 
      Console.Write("Presee any key to continue"); 
      Console.Read(); 
      sck.Close(); 
     } 

所以現在這些演示客戶端,服務器都能夠很好的通信。

實際上,聽者在哪裏起作用?我們建立連接併發送一些請求。 sck.Listen(100);將套接字置於監聽狀態。 他們會在同一端口發送響應嗎?我需要使用Tcplistener類嗎? http://msdn.microsoft.com/en-us/library/bb397809%28v=vs.90%29.aspx。 請建議

謝謝

回答

0

我問的這個問題在幾年前。

我的代碼示例是非常完整的,所以你可能想考慮看看吧:

TCP Client Connection

基本上,你的服務器將是接收器。

客戶端將消息發送到你的服務器是這樣的:

private int sendUsingTcp(string location) { 
    string result = string.Empty; 
    try { 
    using (var fs = new FileStream(location, FileMode.Open, FileAccess.Read)) { 
     using (var client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) { 
     byte[] riteBuf = new byte[client.SendBufferSize]; 
     byte[] readBuf = new byte[client.ReceiveBufferSize]; 
     using (var ns = client.GetStream()) { 
      if (ns.CanRead && ns.CanWrite) { 
      int len; 
      string AOK = string.Empty; 
      do { 
       len = fs.Read(riteBuf, 0, riteBuf.Length); 
       ns.Write(riteBuf, 0, len); 
       int nsRsvp = ns.Read(readBuf, 0, readBuf.Length); 
       AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp); 
      } while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK"))); 
      result = AOK; 
      return 1; 
      } 
      return 0; 
     } 
     } 
    } 
    } catch (Exception err) { 
    MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0); 
    return -1; 
    } 
} 

基本上,之後我做了寫:ns.Write(riteBuf, 0, len);

我讀:ns.Read(readBuf, 0, readBuf.Length);

爲了有需要閱讀的東西,您的服務器上的代碼必須配置爲在收到數據後發送響應。

我的服務器配置是這樣的:

using (var ns = client.GetStream()) { 
    if (ns.CanRead && ns.CanWrite) { 
    int len; 
    byte[] AOK = Encoding.ASCII.GetBytes("AOK"); 
    using (var fs = new FileStream(location, FileMode.Create, FileAccess.Write)) { 
     do { 
     len = ns.Read(buf, 0, client.ReceiveBufferSize); 
     fs.Write(buf, 0, len); 
     ns.Write(AOK, 0, AOK.Length); 
     } while ((0 < len) && ns.DataAvailable); 
    } 
    byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server"); 
    ns.Write(okBuf, 0, okBuf.Length); 
    } 
} 

我希望是明確的。

UPDATE:

如果你需要一個特定的消息中返回,可以做,但我不知道你需要在你的數據添加。

private const string FMT_REPLY = 
    "POST_/OKMMISPOS_HTTP/5.1 " + 
    "Content-Length:_521 ISA*00*" + 
    "__________*00*" + 
    "__________*ZZ*500000330" + 
    "______*ZZ*731476619" + 
    "______*090303*1414*U*004"; 

順便說一句,這是一個討厭的消息。

使用上面定義的常量,你會修改代碼爲:

byte[] AOK = Encoding.ASCII.GetBytes(FMT_REPLY); 
    using (var fs = new FileStream(location, FileMode.Create, FileAccess.Write)) { 
     do { 
     len = ns.Read(buf, 0, client.ReceiveBufferSize); 
     fs.Write(buf, 0, len); 
     ns.Write(AOK, 0, AOK.Length); 
     } while ((0 < len) && ns.DataAvailable); 
    } 
+0

Hi @ jp2code:你到底在哪裏發送消息到服務器,在哪裏聽完?我可能會在接下來的2小時內加快速度。:) – user575219

+0

已更新,讀取響應的客戶端和發送響應的服務器。當然,您可以將這些回覆編輯爲您想要的任何內容。我選擇了短文「AOK」。 – jp2code

+0

我該如何在傳出消息中添加一個httpheader。我可以簡單地附加到實際的消息。他們期待這樣的事情POST_/OKMMISPOS_HTTP/5.1 的Content-Length:_521 ISA * 00 * ------ * 00 * ------ * ZZ * 500000330 ______ * ZZ * 731476619 ______ * 090303 * 1414 * U * 004 ...我有第二部分到位。不知道發送一個http頭文件的最好方法是什麼 – user575219

0

您不必使用TCPListener類的一切,你可以簡單地使用Socket.Listen用於此目的。我拉起一些代碼,我已經在半年前還是這麼寫的(並且仍在使用):

  _listenerThread = new Thread(() => 
      { 
       // Set up our server socket and set it to reuse addresses. 
       ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
       ServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

       // Bind it to the local server. 
       ServerSocket.Bind(new IPEndPoint(IPAddress.Any, PortNumber)); 

       ServerSocket.Listen(MaxQueueLength); 

       // Once we get an incoming connection, let the HandleClientConnection handle it further. 
       ServerSocket.BeginAccept(HandleClientConnection, ServerSocket); 
      }); 

      _listenerThread.Start(); 

在這種特定的情況下,我有我的聽衆一個單獨的線程,一旦請求進來我的ServerSocket對象,HandleClientConnection被調用,這基本上是客戶端和服務器之間的握手。

要確保我們繼續偵聽新連接,我們已經接受並註冊了一個進來後,我增加了以下內容的HandleClientConnectionfinally塊:

  // Whatever happens, we want to make sure we start listening to incoming connections after handling the current one. 
      ServerSocket.BeginAccept(HandleClientConnection, result.AsyncState); 

這樣做有什麼本質上是創建一個圈子;每當新客戶端連接時,服務器接受它,爲它創建一個新的ClientConnection對象,並返回BeginAccept來偵聽新客戶端。

我申請完全一樣的,當涉及到來自客戶端的處理消息。在code review上有一段非常有用的代碼,這是我關閉上述代碼的基礎。