截断传入套接字消息

时间:2012-02-29 18:48:27

标签: bytearray truncated

此代码是我的套接字侦听程序的spinet。问题是我没有得到整个信息。我收到了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 
                { 

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

Socket.Receive()只会获得每次调用的第一个数据报。验证第一次调用中客户端发送的字节数超过1382个字节。

如果有更多数据需要发送,则要么客户端将其排队等待一个Send调用,要么连续调用Receive()并附加到另一个缓冲区,直到您知道它已完成为止。

编辑举例: 您正在寻找的是非阻塞IO。实现它的一种方法是排除here。如果每个客户端连接都有一个类,它可能如下所示:

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线程。