C#套接字问题

时间:2009-11-24 11:39:06

标签: c# php sockets

我在C#中创建一个套接字服务器,在PHP中创建一个客户端。客户端和服务器之间的对话是这样的:

  1. 客户端连接
  2. 服务器发送欢迎信息
  3. 客户端发送数据
  4. 服务器发送响应
  5. (重复步骤3 - 4直到客户端断开连接)
  6. 直到第3步。客户端的数据由服务器接收。但是,客户端会一直等待,直到服务器发送响应并最终超时。

    以下是相关的C#代码:

    class Program
    {
        private const int CONNECT_QUEUE_LENGTH = 4;
    
        static void ListenForRequests()
        {
            Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listenSock.Bind(new IPEndPoint(IPAddress.Any, 9999));
            listenSock.Listen(CONNECT_QUEUE_LENGTH);
            listenSock.Blocking = true;
    
            byte[] data = new byte[1024];
    
            while (true)
            {
                Socket newConnection = listenSock.Accept();
                newConnection.Blocking = true;
    
                // Create new thread for each request
                var t = new Thread(() => new RequestHandler(newConnection));
                t.Start();
            }
        }
    }
    
    class RequestHandler
    {
        public RequestHandler(Socket socket)
        {
            Util.WriteToSocket("A message", socket);
            Console.WriteLine("Received: " + Util.ReadSocketToEnd(socket).Length);
            Util.WriteToSocket("Fin!", socket);
        }
    }    
    
    static class Util
    { 
        public static string ReadSocketToEnd(Socket newConnection)
        {
            var sb = new StringBuilder();
    
            byte[] data = new byte[1024];
            int receivedDataLength = newConnection.Receive(data);
    
            while (receivedDataLength > 0)
            {
                try
                {
                    sb.Append(Encoding.UTF8.GetString(data, 0, receivedDataLength));
                    receivedDataLength = newConnection.Receive(data);
                }
                catch (SocketException)
                {
                    break;
                }
            }
    
            return sb.ToString();
        }
    
        public static void WriteToSocket(string message, Socket client)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            client.Send(data, SocketFlags.None);
        }
    }
    

    这是简单的PHP客户端,没有任何错误处理等:

    <?php
    
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    $result = socket_connect($socket, '127.0.0.1', 9999);
    
    print 'receiving: ' . chr(10);
    print socket_read ($socket, 10) . chr(10);
    print 'receive end' . chr(10);
    
    
    $message = str_repeat("Message to sent", 1000);
    socket_write($socket, $message, strlen($message));
    print 'message sent' . chr(10);
    
    
    print 'reading fin' . chr(10); // This is printed, but a response is never received
    print socket_read ($socket, 10) . chr(10);
    print 'fin read!' . chr(10);
    
    socket_shutdown($socket);
    

1 个答案:

答案 0 :(得分:5)

您正在读取套接字,直到所有数据已被读取 - 这意味着“所有数据直到套接字关闭”。您的PHP客户端正在写入数据,但没有关闭套接字 - 所以服务器正在等待。

TCP套接字提供数据。没有“当前消息结束”的概念,这就是你想要的。

处理此问题的三种方法通常是:

  • 邮件分隔符(例如换行符)
  • 消息长度前缀(消息本身之前的消息中的字节数)
  • 为每个请求/响应对使用不同的连接

可以潜在地使用带有超时的读取,并假设如果你在过去的5秒内没有看到任何更多的数据,你就得到了整个信息 - 但这很脆弱,效率低下,通常是个坏主意。