C# UDP Socket notes

Posted by stringfield on Tue, 11 Jan 2022 00:46:09 +0100


(all notes are from C# official documents) address)

Network related common interfaces

Get local IP

//Obtain IP through network interface description

       public static string GetLocalIP_LAN80211()
        {
            //GetAllNetworkInterfaces returns an object describing the network interface on the local computer.
            foreach (var interfaces in NetworkInterface.GetAllNetworkInterfaces())
            {
                //The type of NetworkInterfaceType network interface. The Wireless80211 network interface uses wireless LAN connection (IEEE 802.11 standard).
                //OperationalStatus specifies the operation status of the network interface. The Up network interface is running and can transmit packets.
                if (interfaces.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 && interfaces.OperationalStatus == OperationalStatus.Up)
                {
                    //GetIPProperties returns an object that describes the configuration of this network interface.
                    //IPInterfaceProperties provides information about network interfaces that support Internet Protocol version 4 (IPv4) or internet protocol version 6 (IPv6).
                    //UnicastAddresses gets the unicast address assigned to this interface.
                    foreach (var ip in interfaces.GetIPProperties().UnicastAddresses)
                    {
                        //Address of InterNetwork IP version 4. Address of InterNetworkV6 IP version 6.
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            //192. At the beginning, it is guaranteed to obtain the intranet address
                            if (ip.Address.ToString().StartsWith("192."))
                                return ip.Address.ToString();
                        }
                    }
                }
            }

            return string.Empty;
        }
//Resolve local IP through DNS
        public static string GetLocalIP_V2()
        {
            try
            {
                //Gets the host name of the local computer.
                string HostName = Dns.GetHostName();
                //Resolve the host name or IP address to an IPHostEntry instance.
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                //AddressList gets or sets the list of IP addresses associated with the host.
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    //Filter out IPv4 type IP addresses from the IP address list
                    //AddressFamily.InterNetwork indicates that this IP is IPv4,
                    //AddressFamily.InterNetworkV6 indicates that this address is IPv6 type
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        string ip = "";
                        ip = IpEntry.AddressList[i].ToString();
                        return IpEntry.AddressList[i].ToString();
                    }
                }
                return "";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

UDP

namespace System.Net.Sockets
class UdpClient

brief introduction

Detailed description (forwarding)
Simply put, transport layer, connectionless, unreliable, broadcast multicast solution

initialization

  • UdpClient constructor (commonly used and other constructors)
    • UdpClient()
      To use this constructor, you need to call Connect Method to specify the remote host
    • UdpClient(Int32)
      The parameter is the port number to be bound. Use this constructor to accept all broadcasts on the same port
    • UdpClient(IPEndPoint)
      The parameter is the IP address to be bound. Use this constructor to receive only the broadcast of the incoming IP

(if receiving broadcast is not considered, the sender can set a port at will)

use

  • Broadcast
    method UdpClient.Send
    If it is a udp object created by UdpClient() parameterless constructor, you can only call Connect first and then Send(Byte[], Int32) to broadcast
    In other cases, Send(Byte[], Int32, IPEndPoint) is called to broadcast. The last parameter is the IP and port specified for broadcasting
  • Receive broadcast
    UdpClient.Receive(IPEndPoint)
    If the thread needs to be opened, it will block
    UdpClient.ReceiveAsync
    (invincible in the world!)
        public async void ListenAsync()
        {
            while (true)
            {
                if (udpClient != null)
                {
                    try
                    {
                        OnGetMessage(await udpClient.ReceiveAsync());
                    }
                    catch
                    {
                        break;
                    }
                }
            }
        }

        private void OnGetMessage(UdpReceiveResult receive)
        {
            string msg = Encoding.UTF8.GetString(receive.Buffer);
            //UnityEngine.Debug.Log($"OnGetMessage ip:{receive.RemoteEndPoint} msg:{msg}");
            EventOnGetMessage?.Invoke(receive.RemoteEndPoint, msg);
        }

If asynchronous execution is performed, call UdpClient. After close, an error will be reported in the await line of code, but it seems to have no impact on the function

Socket

brief introduction

Detailed description (forwarding)
Relationship between Socket and TCP/IP

Tell a joke
Q: what is the relationship between socket and websocket?
A: the relationship between java and JavaScript is the same.

namespace System.Net.Sockets
class Socket

Server

  • create object
    		try
    		{
    			//1.0 instantiation socket (IP4 search protocol, streaming protocol, TCP protocol)
    			_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    			//IP is local IP and port
    			IPAddress ip = IPAddress.Parse(IP);
    			IPEndPoint endPoint = new IPEndPoint(ip, Port);
    			//Bind socket
    			_socket.Bind(endPoint);
    			//Set maximum number of links
    			_socket.Listen(MaxValue);
    			//Start listening
    			ListenClientConnectAsync();
    		}
    		catch (Exception e)
    		{
    			Console.WriteLine(e.ToString());
    			throw;
    		}
    
  • Listen for client links
    Socket clientSocket = await _socket.AcceptAsync();
    

Both a synchronous (blocking) and an asynchronous are Socket objects that provide operations on newly accessed clients. In other words, each obtained Socket corresponds to a connected client. To receive and send client messages, you need to operate the specified Socket object.

  • Receive client information
    Socket.Receive
    	private void ReceiveMessage(object socket)
    	{
    		Socket clientSocket = socket as Socket;
    		string tmpIP = clientSocket.RemoteEndPoint.ToString();
    
    		if (clientSocket != null)
    			dicClientSocket.Add(tmpIP, clientSocket);
    
    		while (clientSocket != null&&clientSocket.Connected)
    		{
    			try
    			{
    				int length = clientSocket.Receive(buffer);
    				string msg = Encoding.UTF8.GetString(buffer, 0, length);
    
    				if (!CheckSocketIsConnect(clientSocket))
    					throw new Exception("Broken link");
    
    				//Client message event received
    				OnGetMsg(clientSocket.RemoteEndPoint.ToString(), msg);
    			}
    			catch (Exception e)
    			{
    				if (clientSocket != null)
    				{
    					//Client disconnect event
    					OnClientDisconnect(tmpIP);
    					dicClientSocket.Remove(tmpIP);
    
    					//clientSocket.Shutdown(SocketShutdown.Both);
    					clientSocket.Close();
    
    					clientSocket = null;
    				}
    				break;
    			}
    		}
    	}
    
    After the client disconnects the link abnormally, it will keep receiving null characters, and the client link state is judged manually
    ReceiveAsync method can't directly await, so it's not very convenient, so thread Start(clientSocket);
  • Send information to clients
    Socket.Send
    If you want to send the content to byte[] and then call send, it will be done.

client

  • Connect server
		public void StartClient()
        {
            try
            {
                //1.0 instantiated socket (IP4 addressing address, streaming, TCP protocol)
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //The IP is the server IP, and the port is
                IPAddress ip = IPAddress.Parse(IP);
                IPEndPoint endPoint = new IPEndPoint(ip, Port);
                //Establish link
                _socket.Connect(endPoint);

				Thread thread = new Thread(ReceiveMessage);
				thread.Start(_socket);
			}
            catch (Exception e)
            {
				UnityEngine.Debug.LogError("link failure : " + e);
                throw;
            }
        }
  • Receiving and sending messages
    It is the same as sending and receiving messages from the server to the Socket

Disconnect Socket link

First judge whether it is a connection state. If so, call it first Socket.Shutdown(SocketShutdown) break link
Then call Socket.Close

try
{
    aSocket.Shutdown(SocketShutdown.Both);
}
finally
{
    aSocket.Close();
}

Judge whether the Socket is connected

Socket.Poll(Int32, SelectMode)
Socket.Connected

		public static bool CheckSocketIsConnect(Socket socket)
        {
			if (socket == null) return false;

			//SelectRead 	 true if listen  has been called and there is a pending connection.
			//-Or - true if there is data to read.
			//-Or - returns true if the connection has been closed, reset, or terminated; Otherwise, false is returned.
			bool part1 = socket.Poll(1000, SelectMode.SelectRead);
			//Gets the amount of data that has been received from the network and is available for reading.
			bool part2 = socket.Available == 0;

			if ((part1 && part2) || !socket.Connected)
				return false;
			else
				return true;
        }

LAN chat implementation

Use the same router or the same mobile hotspot

  • Pure udp implementation
    • Everyone can broadcast udp directly
  • Socket implementation. udp broadcast server IP, others socket link to the server
    • Wait 1 to 2 seconds after opening the application to see if the server IP broadcast is received
      • If the broadcast is received, access the server
      • If not, initialize the server and broadcast your IP address
    • The server forwards the message sent by the client to other clients

Topics: C# network socket