2

まず第一に、私は絶対にネットワーク プログラマーではありません。私がやろうとしているのは、Java サーバーと C# クライアント間の非常に単純な TCP/IP 通信です。

Java サーバー:

 public void run(){   
try {
       // Open server socket
       _server = new ServerSocket(SERVER_PORT);
       _client = _server.accept();
                System.out.println("ComInterface: client connected.");
                // Wait for a client data output stream
                while(true){

                    // Receive message from client
                    BufferedReader is =
                            new BufferedReader(new InputStreamReader(_client.getInputStream()));
                    msg = is.readLine();

                    // Process message
                    if(msg!=null){
                        System.out.println("ComInterface: Message Received : <" + msg + ">.");
                        processMessage(msg); // Independant method
                    }
                    else{
                        System.out.println("ComInterface: client closed connection.");
                        _client.close();
                        _client = _server.accept();
                        System.out.println("ComInterface: client connected.");
                    }

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
}

public void sendMessage(String msg){
        try {

            // Out stream
            DataOutputStream os = new DataOutputStream(_client.getOutputStream());

            os.writeBytes((String)(msg+"\n"+(char)13));
            os.flush();
            System.out.println("ComInterface: Message <" + msg + "> sent");

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }

C# クライアントは次のとおりです。

public class ComInterface : MonoBehaviour
    {
        public const String SERVER_IP = "127.0.0.1"; // Localhost
        public const int PORT = 1100; // Default port 
        public const int READ_BUFFER_SIZE = 5000; // 4.8828125 kilobytes

        private TcpClient _client;
        private ASCIIEncoding _asen;
        private byte[] _readBuffer;
        private String _msg;

        public Boolean connected { get; internal set; } // setter is for internal use only

        /**
         * Initialize internal variables (buffer, socket...)
         */
        public ComInterface()
        {
            connected = false;
            _client = new TcpClient();
            _asen = new ASCIIEncoding();
            _readBuffer = new Byte[READ_BUFFER_SIZE];
            _msg = String.Empty;
        }

        /**
         * Connect to server at SERVER_IP:PORT
         * Return true if connection was a success, or false if failure.
         */
        public Boolean Connect()
        {
            try
            {

                _client.Connect(SERVER_IP, PORT);
                connected = true;
                Array.Clear(_readBuffer, 0, _readBuffer.Length);
                Debug.Log("TCPClient: <Connect> Connected to the server");
                // Start an asynchronous read invoking ReceiveComMessage
                _client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _client.GetStream());
            }
            catch (Exception ex)
            {
                Debug.Log("TCPClient: <Connect> Cannot connect to the server - " + ex.Message);
                connected = false;
            }
            // Return connection state
            return connected;
        }

 /**
         * Received a message from Communicator
         */
        private void ReceiveComMessage(IAsyncResult ar)
        {
            int BytesRead;
            String msg;
            try
            {
                BytesRead = _client.GetStream().EndRead(ar);
                if (BytesRead < 1)
                {
                    // if no bytes were read server has close.  
                    Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (BytesRead<1)");
                    this.Disconnect();
                    return;
                }
                // Convert the byte array the message was saved into,
                msg = Encoding.ASCII.GetString(_readBuffer);
                Debug.Log("C# Message: \"" + msg + "\""); // Output example in log below
                BytesRead = 0;
                Array.Clear(_readBuffer, 0, _readBuffer.Length);

                // Start a new asynchronous read into readBuffer.
                _client.GetStream().BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(ReceiveComMessage), _readBuffer);

            }
            catch (Exception ex)
            {
                Debug.Log("TCPClient: <ReceiveComMessage> The server has closed (Exception):" + ex.Message + " see " + ex.StackTrace);
                this.Disconnect();
            }

主な問題は、すべてのメッセージが不完全に到着することです。ログトレースは次のとおりです。

C#: Message "{
C#: Message ""sender":"Bob"",
C#: Message ""recipient":",
etc...

たとえば代わり​​に

C#: Message "{"sender":"Bob","recipient":[1,2,3]}"

私は少し混乱しており、これを解決するには助けが必要です。どうもありがとうございました!

4

3 に答える 3

3

TCPはストリーム指向の接続であり、メッセージ指向ではありません。メッセージの概念はありません。シリアル化された文字列を書き出すとき、意味のないバイトのシーケンスしか表示されません。TCPは、そのストリームを複数のフラグメントに自由に分割でき、それらはクライアントでそれらのフラグメントサイズのチャンクで受信されます。もう一方の端でメッセージ全体を再構築するのはあなた次第です。

シナリオでは、通常、メッセージ長のプレフィックスを送信します。このようにして、クライアントは最初に長さプレフィックスを読み取り、着信メッセージの大きさを知ることができます。

メッセージを宣言し、サイズプレフィックスオプションを使用してストリーミングするための良い方法として、 Googleのプロトコルバッファのようなものを使用することを真剣に検討します。良い点は、メッセージのセットを一度定義してから、利用可能なツールを使用して、メッセージ定義からC ++、Java、C#などのコードを自動的に生成することです。これは、言語間で機能する一貫したメッセージングセットを持つのに役立ちます。

于 2012-06-28T03:19:19.113 に答える
2

メッセージ (つまり、任意のデータ) は、ソケットを介して送信されると、いくつかのパケットに分割されます。受信した各パケットを印刷すると、メッセージ全体が表示されません。

メッセージ文字列の末尾を定義する必要があります(「.#.」など)。このシーケンスを受信するまで、受信したメッセージを連結し続けます。

これは、セッション プロトコル(つまり、TCP 上で実行されるプロトコル) が行うことです。

お役に立てれば。

よろしく、カリル

于 2012-06-28T02:52:59.997 に答える
0

この例を見てください...

JavaTCPサーバー...

import java.net.*;
import java.io.*;

public class TcpServer
{
    public static void main(String h[])
    {
        try
        {
            ServerSocket serverSocket = new ServerSocket(1100);
            Socket socket = serverSocket.accept();
            System.out.println("Client Accepted");
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("Received: " + bufferedReader.readLine());
            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
            printWriter.println("Hello Theo. Welcome to socket programming.");
        } catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

C#TCPクライアント...

using System;
using System.IO;
using System.Net.Sockets;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var client = new TcpClient("localhost", 1100);
            var stream = client.GetStream();
            var streamWriter = new StreamWriter(stream);
            streamWriter.WriteLine("My name is Theo");
            streamWriter.Flush();
            var streamReader = new StreamReader(stream);
            Console.WriteLine("Received: " + streamReader.ReadLine());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        Console.WriteLine("Press a key to continue.");
        Console.ReadKey();
    }
}
于 2012-06-28T02:56:48.383 に答える