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。请建议

谢谢

4

2 回答 2

0

几年前我问过一个关于这个的问题。

我的代码示例非常完整,因此您可能想看一下:

TCP 客户端连接

基本上,您的服务器将成为侦听器。

客户端将向您的服务器发送一条消息,如下所示:

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);
  }
}

我希望这很清楚。

更新:

如果您需要返回特定消息,可以这样做,但我不知道您需要在哪里添加数据。

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);
    }
于 2013-07-10T20:50:29.830 回答
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就会调用它,这基本上是客户端和服务器之间的握手。

为了确保我们在接受并注册新连接后继续侦听新连接,我将以下内容添加到finally块中HandleClientConnection

            // 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以侦听新客户端。

在处理来自客户的消息时,我应用完全相同的方法。代码审查中有一段非常有用的代码,这是我基于上述代码的。

于 2013-07-10T22:06:41.573 回答