SoFunction
Updated on 2025-03-08

C# Network Programming TCP

1. Overview

UDP and TCP are two commonly used transmission protocols for network communication. C# can generally implement UDP and TCP communication through Socket. Since the .NET framework encapsulates Socket through UdpClient, TcpListener, and TcpClient, making it more convenient to use. This article will explain the related applications through these encapsulated classes.

2. Basic applications: connection, sending, receiving

The server establishes listening and waits for the connection:

TcpListener tcpListener = new TcpListener(("127.0.0.1"), 9000);
();
if (())
{
   TcpClient client = ();
   ("Connected"); 
}

The server obtains the TcpClient object through the AcceptTcpClient method, while the client directly creates the TcpClient object.

TcpClient tcpClient = new TcpClient();
("127.0.0.1", 9000);

After the sending data is created, the sending and receiving are completed through the TcpClient object.

Send data:

TcpClient tcpClient = new TcpClient();
    ("127.0.0.1", 9000);
    NetworkStream netStream = ();

    int Len = 1024;
    byte[] datas = new byte[Len];

    (datas, 0, Len);    

    ();
    ();

Receive data:

TcpClient client = ();
("Connected"); 
 
 NetworkStream stream = ();
 var remote = ;

 byte[] data = new byte[1024];
 while (true)
 {
   if ()
   {
    int len = (data, 0, 1024);
    ($"From:{remote}:Received ({len})");
   }
  (1);
 }

3. Problem of sticking

Unlike UDP, TCP connection will not lose packets, but there is a problem of sticking packets. (Strictly speaking, the statement of sticking packets is not rigorous, because TCP communication is based on streams and does not have the concept of packages. Packages are just the user's own understanding.) Let's analyze the reasons and solutions for sticking packets.

TCP data communication is implemented based on streams, similar to a queue. When data is sent, the operating system will place the sent data into this queue in turn. For the sender, the data is sent piece by piece, so it is naturally believed that there is a concept of data packets. However, for the receiver, if the data is not retrieved in time, the data will be stored in the queue in turn, and there is no obvious gap between each other, so the packet will naturally be stuck.

There is another situation where sticking packets are caused by the sending end. Sometimes when we call the sending code, the operating system may not send it immediately, but put it in the cache area, and it will only be sent when the cache area reaches a certain number.

To solve the problem of sticking, there are roughly the following solutions.

1. The data length is agreed upon, and the data on the sending end is specified, such as 1024; the receiving end also takes the same length when it fetches data. If it is not enough, wait to ensure that the retrieved data is consistent with the sending end;

2. The frequency of data fetching at the receiving end is much greater than that of the sending end. For example, the sending end sends a piece of data every 1 second, and the receiving end fetches data every 0.1 second, so that the data will not stick together;

Both of the above solutions require the sending end to send immediately and data cannot be cached. Moreover, both solutions have shortcomings: First, the first solution: If the packet size is the same, if the agreed packet is larger, there will definitely be more data redundancy and a waste of network resources. If the packet is smaller, the connection will be more frequent and the efficiency will be low.

Secondly, the second solution: This solution can only be implemented in an ideal environment. When the server encounters computing pressure for a period of time, accidents may occur and cannot be completely guaranteed.

A more complete solution is to preprocess the received data: first, by defining a special character combination as the packet header and packet tail, if ASCII characters are transmitted, 0x02 can be used to represent the start (STX) and 0x03 can be used to represent the end (ETX), such as: STX ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ETX (binary data: 02 48 65 6C 6C 6F 03). If the data is long, you can leave a fixed position to store the package length at the package header, such as:

02 00 05 48 65 6C 6C 6F 03

Among them, 02 05 means that the length of the text is 5 bytes, which can be checked.

Although the third solution is relatively rigorous, it is relatively complex. In scenarios where transmission is relatively reliable and application is relatively simple, the first two solutions can also be used.

4. A complete routine

Server:

using System;
using ;
using ;
using ;
using ;
using ;
using ;
using ;
using ;

namespace TCPServer
{
 class Program
 { 
  static void Main(string[] args)
  { 
   TcpListener tcpListener = new TcpListener(("127.0.0.1"), 9000);
   ();

   while (true)
   {
    if (())
    {
     TcpClient client = ();
     ("Connected");     

     (() =>
     { 
      NetworkStream stream = ();
      var remote = ;
      
      while (true)
      {
       if ()
       {
        byte[] data = new byte[1024];
        int len = (data, 0, 1024);
        string Name = Encoding.(data,0,len);
        var senddata = Encoding.("Hello:" + Name);
        (senddata, 0, );
       }

       if (!())
       {
        ("Connect Closed.");
        break;
       }

       (1);
      }
     });
    }

    (1);
   }
  }
 }

 public static class TcpClientEx
 {
  public static bool IsOnline(this TcpClient client)
  {
   return !(((15000, ) && ( == 0)) || !);
  }
 }
}

Client:

using System;
using ;
using ;
using ;
using ;
using ;
using ;
using ;
using ;

namespace TCP_Clent
{
 class Program
 {
  static void Main(string[] args)
  {
   (100, 100);
   (200, 200); 

   (1, 10, x =>
   {
    SendData("Tom");
   });

   ("All Completed!");
   ();
  }

  private static void SendData(string Name)
  {
   (() =>
   {
    ("Start");
    TcpClient tcpClient = new TcpClient();
    ("127.0.0.1", 9000);
    ("Connected");
    NetworkStream netStream = ();

    (() =>
    {
     (100);
     while (true)
     {
      if (!)
      {
       break;
      }

      if (netStream == null)
      {
       break;
      }

      try
      {
       if ()
       {
        byte[] data = new byte[1024];
        int len = (data, 0, 1024);
        var message = Encoding.(data, 0, len);
        (message);
       }
      }
      catch
      {
       break;
      }

      (10);
     }
    });

    for (int i = 0; i < 100; i++)
    {
     byte[] datas = Encoding.(Name);
     int Len = ;
     (datas, 0, Len);
     (1000);
    }

    ();
    netStream = null;
    ();

    ("Completed");
   });
  }  
 }
}

Portal:

The introduction to C# network programming series includes three articles:

(one)UDP for C# Network Programming

(two)Introduction to C# Network Programming TCP

(three)Introduction to C# Network Programming HTTP

The above is the detailed content of tcp in C# network programming. For more information about tcp in C# network programming, please follow my other related articles!