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 に答える