Read data from socket, send response and close

2020-06-28 13:42发布

问题:

I am working on a c# and php project where the PHP script opens a socket to a c# program and the c# program will read the data and then send a response back.

In the PHP script I have the following:

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);
}

In the C# project I have the following:

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();

The PHP script seems to stay waiting and doesn't finish, I'm guessing its being its because the socket on the c# app to send a response back but I have no idea how to do this. Another problem, in the C# I need to have Console.ReadLine() otherwise the c# program will exit but the PHP Script does then finish as expected.

Basically, what I want to know is this the best way to read the data that is sent on the socket, what is the best way to keep the program running so it keep on listening on the socket and how I send back a reply so that the php script can finish.

Thanks for any help you can provide.

回答1:

I managed to figure this out, after processing the data I need to then send a stream.write which is what sends the reply back.

Below is the code

            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();
            }

Thanks for your help



回答2:

Mr. Boardy's solution is correct but I think doing this by socket is better.

So the socket solution is:

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);
}


回答3:

I am not a php guy by any stretch of the imagination so my answer is contingent upon php being able to respond correctly. On the C# side, create a while/do-while loop that continues to run to accept the next incoming request. Here's a simple example:

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

Make sure to set the NoDelay option so that the information is flushed.



标签: c# php sockets