Make a LAN Chat Tool with Socket

Posted by bigfunkychief on Mon, 19 Aug 2019 15:56:28 +0200

Links to the original text: http://www.cnblogs.com/technology/archive/2010/08/15/1799858.html

Programming becomes a simple communication between the server and the client, but through some methods, the two can be unified, so that the server can also become the client, so that the client can also become the server, so that they can communicate with each other at any time and uninterruptedly. Considering the realization of the most original server and client The steps required for communication between clients are very helpful for writing such programs.

As a server, to declare a Socket A and bind to an IP + the IP specified communication port, such as 127.0.0.1:9050, and then start listening. Listen can listen for connection requests from multiple IP, specifically several clients at the same time, which can be set in the Listen method. A parameter. If Listen sends a connection request to a client, then a new Socket B is defined to communicate with the client. Socket B = A.Accept(). At this time, the client's IP and port can be obtained. IPEndPoint C = IPEndPoint B. RemoteEndPoint, C. Address and C.Port represent the client, respectively. The IP address and port of end C. At this time, the message can be sent to C through B.Send() method, and B.Receive() can receive the information sent by client C.

As a client, you also need to declare a Socket D and bind to an IP+native port that is not occupied, define an IPEndPoint E to indicate the server Socket to be connected, and specify the IP and port of E, so that you can communicate between ports. Then you can try D.Connect(E). After success, data can be sent and received, D.Send(), D.Receive.

When sending a message, the data is transmitted in bytes or byte arrays. For example, when my client D wants to send Hello World, it should write as follows: D.Send(Encoding.ASCII.GetBytes("Hello World"). When receiving a message, it is also in bytes or byte arrays, such as when the server accepts Hello Wo just sent by D. Rld, you can write: Byte [] data = new Byte [1024]; int received Data Length = B. Receive (data); string string data = Encoding. ASCII. GetString (data, 0, received Data Length); string data is Hello World.

The above is just a general description of the communication process between the server and the client, and a specific code example is found on the Internet, which is also pasted for reference. This example does not unify the server and the client, but writes the server and the client respectively.

Server-side code

using  System;
using  System;
using  System.Net;
using  System.Net.Sockets;
using  System.Text;
namespace  tcpserver
{
     ///   <summary> 
     /// Summary of Class1.
     ///   </summary> 
     class  server
    {
         ///   <summary> 
         /// The main entry point of the application.
         ///   </summary> 
        [STAThread]
         static   void  Main( string [] args)
        {
             // 
             //  TODO: Add code here to start the application
             //
            int  recv; // Used to indicate the length of information sent by the client
            byte [] data;// = New byte [1024]; // Used to cache information sent by clients, the information passed through socket must be an array of bytes 
            IPEndPoint ipep = new  IPEndPoint(IPAddress.Any, 9050 ); // Local Pre-used IP and Ports 
            Socket newsock = new  Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            newsock.Bind(ipep); // binding
            newsock.Listen( 10 ); // Monitor
            Console.WriteLine( " waiting for a client  " );
            Socket client = newsock.Accept(); //Execute when there is an available client connection attempt and return a new socket for communication with the client 
            IPEndPoint clientip = (IPEndPoint)client.RemoteEndPoint;
            Console.WriteLine( " connect with client: " + clientip.Address + "  at port: " + clientip.Port);
            string  welcome = " welcome here! " ;
            data = Encoding.ASCII.GetBytes(welcome);
            client.Send(data,data.Length,SocketFlags.None); // Send information 
            while ( true )
            { // Continuous access to information from the client with a dead loop 
                data = new   byte [ 1024 ];
                recv = client.Receive(data);
                Console.WriteLine( " recv= " + recv);
                if  (recv == 0 ) // When the information length is 0, the client connection is disconnected 
                     break ;
                Console.WriteLine(Encoding.ASCII.GetString(data, 0 ,recv));
                client.Send(data,recv,SocketFlags.None);
            }
            Console.WriteLine( " Disconnected from " + clientip.Address);
            client.Close();
            newsock.Close();
        }
    }
}

Client Code

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace tcpclient
{
    ///   <summary> 
    /// Summary of Class1.
    ///   </summary> 
    class client
    {
        ///   <summary> 
        /// The main entry point of the application.
        ///   </summary> 
        [STAThread]
        static void Main(string[] args)
        {
            // 
            //  TODO: Add code here to start the application
            //
            byte[] data = new byte[1024];
            Socket newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            newclient.Bind(new IPEndPoint(IPAddress.Any, 905));
            Console.Write(" please input the server ip: ");
            string ipadd = Console.ReadLine();
            Console.WriteLine();
            Console.Write(" please input the server port: ");
            int port = Convert.ToInt32(Console.ReadLine());
            IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ipadd), port); // IP and Port of Server
            try
            {
                // Because the client is only used to send information to a specific server, there is no need to bind the IP and port of the machine. No need to monitor. 
                newclient.Connect(ie);
            }
            catch (SocketException e)
            {
                Console.WriteLine(" unable to connect to server ");
                Console.WriteLine(e.ToString());
                return;
            }
            int receivedDataLength = newclient.Receive(data);
            string stringdata = Encoding.ASCII.GetString(data, 0, receivedDataLength);
            Console.WriteLine(stringdata);
            while (true)
            {
                string input = Console.ReadLine();
                if (input == " exit ")
                    break;
                newclient.Send(Encoding.ASCII.GetBytes(input));
                data = new byte[1024];
                receivedDataLength = newclient.Receive(data);
                stringdata = Encoding.ASCII.GetString(data, 0, receivedDataLength);
                Console.WriteLine(stringdata);
            }
            Console.WriteLine(" disconnect from sercer ");
            newclient.Shutdown(SocketShutdown.Both);
            newclient.Close();
        }
    }
}

The server and client above are both console applications. The idea of creating a form type is to create another thread, which is responsible for establishing connections between the two ends. If you do not use the method of starting another thread, when waiting for a connection but not connecting, or actively connecting, the server has not yet formed a phase. At the right time, the program will appear unresponsive pseudo-dead state.

When the thread connects the two ports successfully, it lets the program enter a dead loop, which is responsible for receiving messages continuously. The message is displayed in txtGetMsg:

while (true)    // Continuous access to information through a dead cycle
{
    data = new byte[1024];
    recv = newclient.Receive(data);

    uiContext.Send(new SendOrPostCallback(
    state =>
    {
        int txtGetMsgLength = txtGetMsg.Text.Length;
        string recMsg = "Friend:       " + System.DateTime.Now.ToString() + "\n    " +Encoding.Unicode.GetString(data, 0, recv) + "\n";
        txtGetMsg.AppendText(recMsg);
        txtGetMsg.Select(txtGetMsgLength, recMsg.Length - Encoding.Unicode.GetString(data, 0, recv).Length - 1);
        txtGetMsg.SelectionColor = Color.Red;
    }), null);
}

If you press the button to send the message, you send the text in txtSendMsg. I write it in Unicode, so you can send Chinese characters.

private void btnSendMsg_Click(object sender, EventArgs e)
{
    string input = txtSendMsg.Text;
    if (input == "")
    {
        MessageBox.Show("Messages cannot be empty!", "Error sending message");
        txtSendMsg.Focus();
    }
    else
    {
        if (meIsClient)
        {
            newclient.Send(Encoding.Unicode.GetBytes(input));
            string showText = "Me:           " + System.DateTime.Now.ToString() + "\n    "
            + input + "\n";
            int txtGetMsgLength = txtGetMsg.Text.Length;
            txtGetMsg.AppendText(showText);
            txtGetMsg.Select(txtGetMsgLength, showText.Length - 1 - input.Length);
            txtGetMsg.SelectionColor = Color.Blue;
            txtSendMsg.Text = "";
        }
        else
        {
            client.Send(Encoding.Unicode.GetBytes(input));
            string showText = "Me        " + System.DateTime.Now.ToString() + "\n    "
            + input + "\n";
            int txtGetMsgLength = txtGetMsg.Text.Length;
            txtGetMsg.AppendText(showText);
            txtGetMsg.Select(txtGetMsgLength, showText.Length - 1 - input.Length);
            txtGetMsg.SelectionColor = Color.Blue;
            txtSendMsg.Text = "";
        }
    }
}

Running effect of program

Download address: / Files/technology/LAN chat tool.zip

Reprinted at: https://www.cnblogs.com/technology/archive/2010/08/15/1799858.html

Topics: socket encoding ascii IE