0

このコードは、私のソケット リスナー プログラムのスピネットです。問題は、メッセージ全体を受け取っていないことです。1382 バイトを受信して​​います。ただし、コードでわかるように、配列サイズを 15000 に定義しています。

namespace Listener 
{ 
    class Server 
    { 
        static void Main(string[] args) 
        { 
            IPAddress localAddr = IPAddress.Parse(args[0]); 
            System.Console.WriteLine("The local IP is {0}",  
localAddr); 
            Int32 port = int.Parse(args[1]); 
            System.Console.WriteLine("The port is {0}", port); 
            TcpListener myListener = new TcpListener(localAddr,  
port); 
            byte[] bytes = new byte[15000]; 
            string sem = ""; 
            do 
            { 
                Console.Write("Waiting"); 
                myListener.Start(); 
                Socket mySocket = myListener.AcceptSocket(); 
                // receiving the hl7 message             
                mySocket.Receive(bytes); 
                string receiveMessage =  
Encoding.ASCII.GetString(bytes); 
                // write out the hl7 message to a receiving  
folder 
                DateTime currentDate = DateTime.Now; 
                long eTicks = currentDate.Ticks; 
                System.IO.File.WriteAllText(@"y:\results\" +  
eTicks + ".hl7", receiveMessage); 
                // build the acknowledgemnent message to send  
back to the client 
                try 
                { 

助けてくれてありがとう。

4

1 に答える 1

1

Socket.Receive() は、呼び出しごとに最初のデータグラムのみを取得します。最初の呼び出しでクライアント側から送信された 1382 バイトを超えるバイトがあることを確認します。

送信するデータがさらにある場合は、クライアントに 1 回の Send 呼び出しのためにそれをキューに入れるか、継続的に Receive() を呼び出して、完了したことがわかるまで別のバッファーに追加します。

編集例:探しているのは非ブロッキングIOです。それを実装する 1 つの方法をここに示します。クライアント接続ごとにクラスがある場合、次のようになります。

internal class Server
{
    private static void Main(string[] args)
    {
        IPAddress localAddr = IPAddress.Parse(args[0]);
        System.Console.WriteLine("The local IP is {0}",
                                 localAddr);
        Int32 port = int.Parse(args[1]);
        System.Console.WriteLine("The port is {0}", port);
        TcpListener myListener = new TcpListener(localAddr,
                                                 port);
        byte[] bytes = new byte[15000];
        string sem = "";
        do
        {
            Console.Write("Waiting");
            myListener.Start();
            Socket mySocket = myListener.AcceptSocket();
            var clientConn = new ClientConnection(mySocket);
        } while (true);
    }
}

public class ClientConnection
{
    private const int BUFFER_SIZE = 15000;
    readonly private byte[] _buffer = new byte[BUFFER_SIZE];
    readonly private Socket _socket;
    readonly private StringBuilder _output = new StringBuilder();

    public ClientConnection(Socket socket)
    {
        _socket = socket;
        _socket.BeginReceive(_buffer, 0, BUFFER_SIZE, SocketFlags.None, ReadCallback, null);
    }

    private void ReadCallback(IAsyncResult ar)
    {
        var read = _socket.EndReceive(ar);

        if (read > 0)
        {
            // receiving the hl7 message             
            string receiveMessage = Encoding.ASCII.GetString(_buffer, 0, read);
            _output.Append(receiveMessage);

            _socket.BeginReceive(_buffer, 0, BUFFER_SIZE, SocketFlags.None, ReadCallback, null);
        }
        else
        {

            // write out the hl7 message to a receiving  folder
            DateTime currentDate = DateTime.Now;
            long eTicks = currentDate.Ticks;
            System.IO.File.WriteAllText(@"y:\results\" + eTicks + ".hl7", _output.ToString());

            SendAcknowledgement();
        }
    }

    private void SendAcknowledgement()
    {
        // build the acknowledgemnent message to send back to the client 
    }
}

私はこれを確認しませんでしたが、正しい方向に進むはずです。クライアントがデータの送信を完了すると、サーバーはデータの読み取りを停止する必要があると想定しました。また、あなたの do { } は、新しい接続を待つ無限ループの始まりであると想定しました。BeginAccept() を使用して、コードのその部分をノンブロッキングにすることもできますが、必要に応じてユースケースによって異なります。

この方法で開かれたすべての接続は、新しい ThreadPool スレッドになることに注意してください。

于 2012-02-29T19:04:11.810 に答える