【问题标题】:Read data from socket, send response and close从套接字读取数据,发送响应并关闭
【发布时间】:2012-06-04 02:45:51
【问题描述】:

我正在开发一个 c# 和 php 项目,其中 PHP 脚本打开一个到 c# 程序的套接字,c# 程序将读取数据,然后发回响应。

在 PHP 脚本中,我有以下内容:

echo "Opening Client";

$fp = fsockopen("127.0.0.1", 12345, $errno, $errstr, 30);

if (!$fp)
{
    echo "Error: $errstr ($errno)<br />";
}
else
{
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: 127.0.0.1\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp))
    {
        echo fgets($fp, 128);
    }
    fclose($fp);
}

在 C# 项目中,我有以下内容:

public void startListen()
        {
            int port = 12345;
            IPAddress serverAddress = IPAddress.Parse("127.0.0.1");
            TcpListener listener = new TcpListener(serverAddress, 12345);
            listener.Start();

            TcpClient client = listener.AcceptTcpClient();

            NetworkStream stream = client.GetStream();
            byte[] data = new byte[client.ReceiveBufferSize];
            int bytesRead = stream.Read(data, 0, Convert.ToInt32(client.ReceiveBufferSize));
            string request = Encoding.ASCII.GetString(data, 0, bytesRead);
            Console.WriteLine(request);

            Console.ReadLine();

PHP 脚本似乎一直在等待并且没有完成,我猜它是因为 c# 应用程序上的套接字发送回响应,但我不知道该怎么做。另一个问题,在 C# 中我需要 Console.ReadLine() 否则 c# 程序将退出,但 PHP 脚本会按预期完成。

基本上,我想知道这是读取在套接字上发送的数据的最佳方式,保持程序运行以使其继续侦听套接字的最佳方式是什么以及我如何发回回复以便 php 脚本可以完成。

感谢您提供的任何帮助。

【问题讨论】:

  • 在您的 C# 代码中……您实际上并没有向流中写入任何内容?我猜应该有一些 stream.Write() 方法用于发送数据。另一方面:你确定你在正确的抽象级别上工作吗? .NET 中没有 StreamReader/StreamWriter 类可以更轻松地与(套接字)流交互吗?

标签: c# php sockets


【解决方案1】:

无论如何,我都不是一个 php 人,所以我的答案取决于 php 是否能够正确响应。在 C# 端,创建一个 while/do-while 循环,该循环继续运行以接受下一个传入请求。这是一个简单的例子:

http://www.csharp-examples.net/socket-send-receive/

确保设置 NoDelay 选项以便刷新信息。

【讨论】:

    【解决方案2】:

    我设法弄清楚了这一点,在处理完数据后我需要发送一个 stream.write ,这就是发送回复的内容。

    下面是代码

                int port = 12345;
                IPAddress serverAddress = IPAddress.Parse("127.0.0.1");
                TcpListener listener = new TcpListener(serverAddress, port);
                listener.Start();
    
                while (true)
                {
                    TcpClient client = listener.AcceptTcpClient();
    
                    NetworkStream stream = client.GetStream();
                    byte[] data = new byte[client.ReceiveBufferSize];
                    int bytesRead = stream.Read(data, 0, Convert.ToInt32(client.ReceiveBufferSize));
                    string request = Encoding.ASCII.GetString(data, 0, bytesRead);
                    Console.WriteLine(request);
                    byte[] msg = System.Text.Encoding.ASCII.GetBytes("200 OK");
    
                    // Send back a response.
                    stream.Write(msg, 0, msg.Length);
                    client.Close();
                }
    

    感谢您的帮助

    【讨论】:

    • 这里关闭TcpClient意味着杀掉它!
    • 这是我需要它做的不是吗。一旦它发送了回复,客户端就完成了,不应该再向套接字发送任何数据,所以我关闭了连接。
    • 我需要继续与客户端通信,假设它是一个聊天应用程序,我们不希望客户端连接并发送成功标记并完成,我们想进一步沟通。
    【解决方案3】:

    先生。 Boardy 的解决方案是正确的,但我认为通过套接字这样做更好。

    所以socket解决方案是:

    private void Form3_Load(object sender, EventArgs e)
    {
        sc_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint ip_local = new IPEndPoint(IPAddress.Loopback, 1225);
        sc_listener.Bind(ip_local);
        sc_listener.Listen(10);
    
        AsyncCallback callback = new AsyncCallback(procces_incoming_socket);
        sc_listener.BeginAccept(callback, sc_listener);
    }
    
    void procces_incoming_socket(IAsyncResult socket_object)
    {
        Socket sc_listener = ((Socket)socket_object.AsyncState).EndAccept(socket_object);
    
        AsyncCallback receive = new AsyncCallback(receive_data);
        buffer = new byte[100];
        sc_listener.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receive, sc_listener);
    }
    
    void receive_data(IAsyncResult socket)
    {
        // the system need to wait so i make a loop when it gets data 
        //i end the loop by flag=false
        bool flag = true;
        Socket re_socket = ((Socket)socket.AsyncState);
        while(flag)
        {
            int bytes_recieved = re_socket.EndReceive(socket);
    
            string data = UTF8Encoding.UTF8.GetString(buffer);
            if (textBox1.InvokeRequired)
            {
                // for cross thread problem
                textBox1.Invoke(new MethodInvoker(delegate { textBox1.Text = data; }));
            }
            else
            {
                textBox1.Text = data;
            }
            flag = false;
        }
        string back_data = "my pm socket back";
        byte[] buffers = new byte[50];
        buffers = UTF8Encoding.UTF8.GetBytes(back_data);
        re_socket.Send(buffers);
        // if the socket is not closed php will load for maximum required time and then error
        re_socket.Close();
        //start for next listening (O-0)
        AsyncCallback callback = new AsyncCallback(procces_incoming_socket);
        sc_listener.BeginAccept(callback, sc_listener);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 2011-09-05
      • 2020-12-24
      • 2014-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多