简体   繁体   中英

Working on client server using sockets and tcp\ip in C#

I am working on client-server data receiving. I am able to receive data from the server which is my meter. The code is below

listner = new TcpListener(new IPEndPoint(IPAddress.Any, port));
        Console.WriteLine("Listening...");
        listner.Start();
        while (true)
        {
            try
            {
                //---incoming client connected---
                TcpClient client = listner.AcceptTcpClient();

                //---get the incoming data through a network stream---
                NetworkStream nwStream = client.GetStream();
                byte[] buffer = new byte[client.ReceiveBufferSize];

                //---read incoming stream---
                int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);

                //---convert the data received into a string---
                string dataReceived = BitConverter.ToString(buffer, 0, bytesRead);
                //Encoding.ASCII.GetString(buffer, 0, bytesRead);
                //Console.WriteLine("Received : " + dataReceived);
                //MessageBox.Show("Data Received", dataReceived);
                //---write back the text to the client---
                //Console.WriteLine("Sending back : " + dataReceived);
                //nwStream.Write(buffer, 0, bytesRead);
                client.Close();
            }
            catch (Exception ex)
            {

            }

Using the above code I am able to receive the data. But I want to perform the following

  1. Keeping listening on the port
  2. While listening I want to send some bytes to the server (meter)
  3. Get a response from the server after sending some data.

I know there are lots of client-server tutorials but they have a separate implementation of server and client. I just want to handle the client(my software). I have also tried with Asynchronous Server Socket Example .

Any help would be highly appreciated.

Your server needs to continually listen for connections from clients. Each time it gets a connection you get from the OS a new TcpClient to handle that connection. the TcpClient that you get from the OS is sometimes called a Child TcpClient because it's created by the listening port. But it's functionally the same as any other socket.

This is very easy to achieve with the async/await pattern.

First you need a listener that waits for connections, everytime it gets a connection it passes this off to another task that processes the child TcpClient. eg,

static async Task StartTcpServerAsync()
{
    var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
    tcpListener.Start();

    while (true)
    {
        var tcpClient = await tcpListener.AcceptTcpClientAsync();

        // Fire and forget the Child connection
        _ = StartChildTcpClientAsync(tcpClient);
    }
}

In the above boiler plate code we're completely forgetting about the ChildTcpClient task. You might or might not want this. If you make the task completely self sufficient (as this demo is) then the main task may never need to know if it finished or not. But if you need to be able to provide feedback between the ChildTcpClient Task and the main task then you'll need to provide some additional code to manage this and you'd start by storing the Task returned from StartChildTcpClientAsync(tcpClient); somewhere so you can observe it. You could use Task.Run() here, but it is not necessary in a Console application.

Now that you've got your listener Task, you need a ChildTcpClient Task, eg:

static async Task StartChildTcpClientAsync(TcpClient tcpClient)
{
    Console.WriteLine($"Connection received from: {tcpClient.Client.RemoteEndPoint.ToString()}");

    using var stream = tcpClient.GetStream();
    var buffer = new byte[1024];
    while (true)
    {
        var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
        await stream.WriteAsync(buffer, 0, bytesRead);
    }
}

That's a super simple Tcp echo client. It's got no flow control and no error handling the task will just sit there forever waiting for the client to send some data even after the client has disconnected. This Task just "awaits" for infinity (or until an exception occurs) so you need to add some code in here to manage the client, check that the client is still connected, etc etc

To pull it all together you simply need a main like this:

static async Task Main(string[] args)
{
    await StartTcpServerAsync();
    // Will never exit unless tcpListener.AcceptTcpClientAsync();
    // throws an exception
}

And that's it, you have a Console Application that waits for an infinite number of clients to connect, and each time one does it has it's own Task to deal with the IO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM