2013-07-10 90 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上有一段非常有用的代码,这是我关闭上述代码的基础。