One: what is a SOCKET
The original meaning of socket in English is “hole” or “socket”. As a process communication mechanism, take the latter meaning. Also known as a socket, it is used to describe an IP address or port and is a handle to a communication chain. A socket is very similar to a telephone socket. Take a telephone network as an example: The two parties on a telephone are equivalent to two programs communicating with each other, and the telephone number is the IP address. Before making a call, any user must first possess a telephone, which is equivalent to applying for a socket. At the same time, you need to know the number of the peer party, which means that the peer party has a fixed socket. Then dial a call to the other party, which is equivalent to making a connection request. If the other party is present and free, pick up the phone, both sides can talk formally, equivalent to a successful connection. During a conversation, one party sends signals to the phone and the other party receives signals from the phone, which is equivalent to sending data to the socket and receiving data from the socket. When the call ends, one party hangs up the phone, which is equivalent to closing the socket and revoking the connection.
1, socket classification
In order to meet the requirements of different programs for communication quality and performance, common network systems provide the following three different types of sockets for users to choose according to different needs when designing programs:
Streaming socket (SOCK_STREAM) : provides a reliable, connection-oriented two-way data transfer service. Data error – free, no repeated transmission, internal flow control, the transmitted data is regarded as no record boundary byte stream. In TCP/IP protocol cluster, TCP is used to realize the transmission of byte stream. When users want to send large quantities of data, or have high requirements on the reliability of data transmission, streaming socket is used.
Datagram socket (SOCK_DGRAM) : provides a connectionless, unreliable two-way data transfer service. Data is sent in a separate package with record boundaries preserved and no reliability assurance provided. Data may be lost or duplicated during transmission, and data cannot be received in the order in which it is sent. In the TCP/IP protocol cluster, datagram sockets are implemented using UDP.
Raw socket (SOCK_RAW) : This socket allows direct access to lower level protocols such as IP or ICMP. Generally used for TCP/IP core protocol network programming.
Two: Concepts related to sockets
1, ports,
There are many such hosts on the Internet, which typically run multiple service software and provide several services simultaneously. Each service opens a Socket and is bound to a port. Different ports correspond to different services (applications). Therefore, port numbers are used in network protocols to identify different processes on the host. For example, HTTP uses port 80 and FTP uses port 21.
2, protocols,
TCP 2.1:
TCP is a connection-oriented, reliable, byte stream – based transport-layer communication protocol. Provides highly reliable data communication services for two hosts. It can transmit data from the source host to the target host without error. When there is data to be sent, the data sent by the application process is fragmented for transmission in the network layer. When receiving packets from the network layer, it must confirm the received packets and set timeout resending for the lost packets. Therefore, TCP needs to add a lot of extra overhead, in order to carry out some necessary control in the process of data transmission, to ensure the reliable transmission of data. Therefore, TCP transmission is inefficient.
2.1.1 TCP Working process
TCP is a connection-oriented protocol. TCP uses three packet segments to establish a connection similar to a telephone call. This process is called three-way handshake, as shown in the following figure:
First handshake: When establishing a connection, the client sends a SYN packet (SEQ= X) to the server and enters the SYN_SEND state for confirmation.
Second handshake: After receiving a SYN packet, the server must acknowledge the client’s SYN (ACK= X +1) and send a SYN packet (SEQ= Y). In this case, the server enters the SYN_RECV state.
Third handshake: After receiving the SYN+ACK packet from the server, the client sends an ACK packet (ACK= Y +1) to the server. After the packet is sent, the client and the server enter the Established state to complete the three-way handshake.
2.1.2 Data Transmission
Once a TCP connection is established, either party in the connection can send and receive data to the other party. TCP protocol is responsible for user data (byte stream) according to a certain format and length of multiple datagrams sent, and after receiving the datagrams in order to reassemble and restore user data. When TCP is used to transmit data, it is transmitted as a byte stream.
2.1.3 Termination of connection
Three handshakes are required to establish a connection, and four handshakes are required to terminate a connection, caused by TCP’s half-close. The specific process is shown in the figure:
2.1.4 Main features of TCP
The main features of TCP are as follows. (1) is a connection-oriented protocol. (2) End-to-end communication. Each TCP connection can have only two endpoints, and only one-to-one communication, not point-to-multipoint direct communication. (3) High reliability. Data transmitted over the TCP connection can ensure that the data reaches the receiver accurately without error, loss, or repetition, and the data arrives in the same order as it is sent out. (4) Full-duplex transmission. (5) Data is transmitted by byte stream. (6) The transmitted data has no message boundary.
2.1.5 Synchronous and Asynchronous
Synchronous working mode refers to the use of TCP programming to monitor or receive statements, in the unfinished work (listening to the connection request or receive the data from the other party) before no further execution, the thread is in a blocked state, until the statement completed the corresponding work will continue to execute the next statement. Asynchronous mode of working means that when a program executes until it hears or receives a statement, it continues to execute regardless of whether the work is complete or not.
2.2 the UDP
UDP is a simple datagram – oriented connectionless protocol that provides unreliable transport services. Connectionless refers to sending a message to the other party regardless of the status of the other party without establishing a connection with the other party. It’s very similar to texting — you just need to know the phone number, regardless of what state the phone is in. Although UDP cannot ensure the reliability of data transmission, data transmission efficiency is high.
2.1.1 Differences between UDP and TCP (1) UDP is less reliable than TCP. TCP has a special transmission guarantee mechanism. When the data receiver receives a message from the sender, it automatically sends an acknowledgement message to the sender. The sender will not proceed with any further transmission until it receives the acknowledgement message, otherwise it will wait until it receives the acknowledgement message. Unlike TCP, UDP does not provide a guarantee mechanism for data transmission. The protocol itself does not detect or indicate any loss of datagrams during transmission from sender to receiver. Therefore, UDP is often referred to as an unreliable transport protocol. (2) UDP cannot guarantee orderly transmission UDP cannot ensure the order of data sending and receiving. For sudden datagrams, it is possible to get out of order.
2.1.2 Advantages of UDP
(1) Faster UDP than TCP Because UDP does not need to establish a connection with the other party, and does not need to confirm transmission, the data transmission speed of UDP is much faster than TCP. For applications that emphasize transmission performance rather than transmission integrity (such as network audio playback, video on demand, and web conferencing), UDP is suitable because of its high transmission speed and good sound quality and clear picture. (2) UDP has message boundary. UDP sends packets to the application program directly to the IP layer after adding headers. Neither split nor merge, but preserve the boundaries of these packets. With UDP, there is no need to worry about message boundaries, which makes UDP programming much more convenient than TCP for handling received data. From the programmer’s point of view, UDP sockets are simpler to use than TCP. This feature of UDP also indicates that it is a message-oriented transmission protocol. (3) UDP can be one-to-many transmission because the transmission of data does not establish a connection, there is no need to maintain the connection state (including the sending and receiving state), so a server can simultaneously transmit the same message to multiple clients. UDP can simultaneously send messages to all client processes on a subnet in broadcast or multicast mode, which is more convenient than TCP. Among them, the speed is the primary advantage of UDP because TCP protocol is embedded in a variety of security functions, in the actual implementation of the process will take up a lot of system overhead, no doubt the speed is seriously affected. In contrast, UDP, due to the abandonment of reliable information transmission mechanism, security and sorting functions handed over to the upper application to complete, greatly reduced the execution time, so that the speed has been guaranteed. In short, UDP’s “philosophy” is “to do whatever it takes to send data faster.”
Three: Socket general application mode:
Four: Basic flow chart of SOCKET communication:
According to the basic flow chart of Socket communication, the basic steps of communication are summarized:
Server side:
Step 1: Create a Socket object to listen for connections.
Step 2: Set up an EndPoint object with the specified port number and the server IP address.
Step 3: Bind the EndPoint with the socket object’s Bind() method.
Step 4: Start listening with the socket object’s Listen() method.
Step 5: After receiving the connection from the client, use the Accept() method of the socket object to create a new socket object for communication with the client.
Step 6: Remember to close the socket after the communication is over;
Client:
Step 1: Create a Socket object;
Step 2: Set up an EndPoint object with the specified port number and the server IP address.
Step 3: Use the socket object’s Connect() method to send a connection request to the server with the EndPoint object established above as a parameter.
Step 4: If the connection succeeds, Send a message to the server using the socket object’s Send() method.
Step 5: Use the socket object Receive() method to Receive the information sent by the server;
Step 6: Remember to close the socket after the communication is over;
Five: WinForm sample procedures
Server interface:
The code implementation is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
namespace SocketServer
{
public partial class FrmServer : Form
{
public FrmServer()
{
InitializeComponent();
}
// Define callbacks: resolve cross-thread access issues
private delegate void SetTextValueCallBack(string strValue);
// Define the callback to receive the message sent by the client
private delegate void ReceiveMsgCallBack(string strReceive);
Declare a callback
private SetTextValueCallBack setCallBack;
/ / declare
private ReceiveMsgCallBack receiveCallBack;
// Define a callback to add elements to the ComboBox control
private delegate void SetCmbCallBack(string strItem);
/ / declare
private SetCmbCallBack setCmbCallBack;
// Define the callback to send the file
private delegate void SendFileCallBack(byte[] bf);
/ / declare
private SendFileCallBack sendCallBack;
// Socket for communication
Socket socketSend;
// SOCKET for listening
Socket socketWatch;
// Store the remote client IP address and Socket into the collection
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
// Create a thread to listen for connections
Thread AcceptSocketThread;
// The thread that receives the message sent by the client
Thread threadReceive;
/// <summary>
/// start listening
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_Start_Click(object sender, EventArgs e)
{
// Create a Socket on the server that listens for IP addresses and port numbers when clicking start listening
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Obtain the IP address
IPAddress ip=IPAddress.Parse(this.txt_IP.Text.Trim());
// Create a port number
IPEndPoint point=new IPEndPoint(ip,Convert.ToInt32(this.txt_Port.Text.Trim()));
// Bind the IP address and port number
socketWatch.Bind(point);
This.txt_log. AppendText(” Listener succeeded “+” \r \n”);
// Start listening: Sets the maximum number of requests that can be connected simultaneously
socketWatch.Listen(10);
// Instantiate callback
setCallBack = new SetTextValueCallBack(SetTextValue);
receiveCallBack = new ReceiveMsgCallBack(ReceiveMsg);
setCmbCallBack = new SetCmbCallBack(AddCmbItem);
sendCallBack = new SendFileCallBack(SendFile);
// Create a thread
AcceptSocketThread = new Thread(new ParameterizedThreadStart(StartListen));
AcceptSocketThread.IsBackground = true;
AcceptSocketThread.Start(socketWatch);
}
/// <summary>
/// wait for the client to connect, and create a Socket to communicate with it
/// </summary>
/// <param name=”obj”></param>
private void StartListen(object obj)
{
Socket socketWatch = obj as Socket;
while (true)
{
// Wait for the client to connect and create a Socket for communication
socketSend = socketWatch.Accept();
// Get the IP address and port number of the remote host
string strIp=socketSend.RemoteEndPoint.ToString();
dicSocket.Add(strIp, socketSend);
this.cmb_Socket.Invoke(setCmbCallBack, strIp);
String strMsg = “remote host:” + socketSend. RemoteEndPoint + “successful connection”;
// Use the callback
txt_Log.Invoke(setCallBack, strMsg);
// Define the thread that receives the client message
Thread threadReceive = new Thread(new ParameterizedThreadStart(Receive));
threadReceive.IsBackground = true;
threadReceive.Start(socketSend);
}
}
/// <summary>
/// The server continues to receive messages from the client
/// </summary>
/// <param name=”obj”></param>
private void Receive(object obj)
{
Socket socketSend = obj as Socket;
while (true)
{
// After the client is successfully connected, the server receives the message from the client
byte[] buffer = new byte[2048];
// The actual number of valid bytes received
int count = socketSend.Receive(buffer);
If (count == 0)//count indicates that the client is closed and to exit the loop
{
break;
}
else
{
string str = Encoding.Default.GetString(buffer, 0, count);
String strReceiveMsg = “received:” + socketSend RemoteEndPoint + “sent messages:” + STR;
txt_Log.Invoke(receiveCallBack, strReceiveMsg);
}
}
}
/// <summary>
/// the method that the callback delegate needs to execute
/// </summary>
/// <param name=”strValue”></param>
private void SetTextValue(string strValue)
{
this.txt_Log.AppendText(strValue + ” \r \n”);
}
private void ReceiveMsg(string strMsg)
{
this.txt_Log.AppendText(strMsg + ” \r \n”);
}
private void AddCmbItem(string strItem)
{
this.cmb_Socket.Items.Add(strItem);
}
/// <summary>
/// The server sends a message to the client
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_Send_Click(object sender, EventArgs e)
{
try
{
string strMsg = this.txt_Msg.Text.Trim();
byte[] buffer = Encoding.Default.GetBytes(strMsg);
List<byte> list = new List<byte>();
list.Add(0);
list.AddRange(buffer);
// Convert a generic collection to an array
byte[] newBuffer = list.ToArray();
// Get the IP address selected by the user
string ip = this.cmb_Socket.SelectedItem.ToString();
dicSocket[ip].Send(newBuffer);
}
catch (Exception ex)
{
Messagebox.show (” error sending Message to client :”+ ex.message);
}
//socketSend.Send(buffer);
}
/// <summary>
/// Select the file to send
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_Select_Click(object sender, EventArgs e)
{
OpenFileDialog dia = new OpenFileDialog();
// Set the initial directory
dia.InitialDirectory = @””;
Dia.Title = “Please select the file to send “;
// Filter file types
All files dia. Filter = “| *. *”;
dia.ShowDialog();
// Assign the full path of the selected file to the text box
this.txt_FilePath.Text = dia.FileName;
}
/// <summary>
/// send the file
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_SendFile_Click(object sender, EventArgs e)
{
List<byte> list = new List<byte>();
// Get the path to the file to send
string strPath = this.txt_FilePath.Text.Trim();
using (FileStream sw = new FileStream(strPath,FileMode.Open,FileAccess.Read))
{
byte[] buffer = new byte[2048];
int r = sw.Read(buffer, 0, buffer.Length);
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
// Invoke btn_sendfile.invoke (sendCallBack, newBuffer);
}
}
private void SendFile(byte[] sendBuffer)
{
try
{
dicSocket[cmb_Socket.SelectedItem.ToString()].Send(sendBuffer, SocketFlags.None);
}
catch (Exception ex)
{
Messagebox.show (” error sending file :”+ ex.message);
}
}
private void btn_Shock_Click(object sender, EventArgs e)
{
byte[] buffer = new byte[1] { 2};
dicSocket[cmb_Socket.SelectedItem.ToString()].Send(buffer);
}
/// <summary>
// stop listening
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_StopListen_Click(object sender, EventArgs e)
{
socketWatch.Close();
socketSend.Close();
// Terminates the thread
AcceptSocketThread.Abort();
threadReceive.Abort();
}
}
}
Client interface
The code implementation is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
namespace SocketClient
{
public partial class FrmClient : Form
{
public FrmClient()
{
InitializeComponent();
}
// Define the callback
private delegate void SetTextCallBack(string strValue);
/ / declare
private SetTextCallBack setCallBack;
// Define the callback for the receiving server to send the message
private delegate void ReceiveMsgCallBack(string strMsg);
/ / declare
private ReceiveMsgCallBack receiveCallBack;
// Create a Socket for the connection
Socket socketSend;
// Create a thread to receive messages sent by the client
Thread threadReceive;
/// <summary>
/ / / connection
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_Connect_Click(object sender, EventArgs e)
{
try
{
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(this.txt_IP.Text.Trim());
socketSend.Connect(ip, Convert.ToInt32(this.txt_Port.Text.Trim()));
// Instantiate callback
setCallBack = new SetTextCallBack(SetValue);
receiveCallBack = new ReceiveMsgCallBack(SetValue);
This.txt_log. Invoke(setCallBack, “connect successfully “);
// Start a new thread to receive messages from the server
threadReceive = new Thread(new ThreadStart(Receive));
// Set it to background thread
threadReceive.IsBackground = true;
threadReceive.Start();
}
catch (Exception ex)
{
Messagebox.show (” Connect server error :” + ex.tostring ());
}
}
/// <summary>
/// Message sent by the interface server
/// </summary>
private void Receive()
{
try
{
while (true)
{
byte[] buffer = new byte[2048];
// The number of bytes actually received
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
else
{
// Determine the type of data to be sent
If (buffer[0] == 0)// indicates that a text message is sent
{
string str = Encoding.Default.GetString(buffer, 1, r – 1);
This. Txt_Log. Invoke (receiveCallBack, “receives the remote server:” + socketSend. RemoteEndPoint + “sent messages:” + STR);
}
// Indicates that a file is sent
if (buffer[0] == 1)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @””;
Sfd. Title = “Please select the file to save “;
All files SFD. Filter = “| *. *”;
sfd.ShowDialog(this);
string strPath = sfd.FileName;
using (FileStream fsWrite = new FileStream(strPath, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(buffer, 1, r – 1);
}
Messagebox.show (” save file successfully “);
}
}
}
}
catch (Exception ex)
{
Messagebox.show (” error receiving server message :” + ex.tostring ());
}
}
private void SetValue(string strValue)
{
this.txt_Log.AppendText(strValue + “\r \n”);
}
/// <summary>
/// The client sends messages to the server
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_Send_Click(object sender, EventArgs e)
{
try
{
string strMsg = this.txt_Msg.Text.Trim();
byte[] buffer = new byte[2048];
buffer = Encoding.Default.GetBytes(strMsg);
int receive = socketSend.Send(buffer);
}
catch (Exception ex)
{
Messagebox.show (” error sending Message :” + ex.message);
}
}
private void FrmClient_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// Disconnect the connection
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void btn_CloseConnect_Click(object sender, EventArgs e)
{
/ / close the socket
socketSend.Close();
// Terminates the thread
threadReceive.Abort();
}
}
}
Six, the console program example
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System;
using System.Text;
Namespace Socket Indicates the Socket
{
class SocketT
{
private Socket _ServerSocket; // The server listens for sockets
private bool _IsListionContect; // Whether to listen
public SocketT()
{
// Define the network end node (encapsulating IP and port)
IPEndPoint endPoint = new IPEndPoint(ipaddress.parse (“127.0.0.1”), 1000); IPEndPoint endPoint = new IPEndPoint(ipaddress.parse (“127.0.0.1”), 1000);
Instantiate the socket
_ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the server address
_ServerSocket.Bind(endPoint);
// Start listening
_ServerSocket.Listen(10); // The maximum length of the listener
Console.WriteLine(” Server started…”) );
try
{
while (true)
{
The Accept() method accepts the connection from the client and blocks the current thread
Socket sockMsgSever = _ServerSocket.Accept();
Console.WriteLine(” There is a client connection…” );
// Start background thread for client session
Thread thClientMsg = new Thread(ClientMsg);
thClientMsg.IsBackground = true; // Set it to background thread
thClientMsg.Name = “thClientMsg”;
thClientMsg.Start(sockMsgSever);
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// The thread after which the server and client communicate
/// </summary>
/// <param name=”?” ></param>
private void ClientMsg(object sokMsg)
{
Socket socketMsg = sokMsg as Socket; // Convert the object type to Socket communication
while (true)
{
// Prepare a data cache
byte[] msyArray = new byte[0124 * 0124];
// Accept the request from the client, return the true data length
int TrueClientMsgLenth = socketMsg.Receive(msyArray);
//byte array to string
string strMsg = Encoding.UTF8.GetString(msyArray, 0, TrueClientMsgLenth);
// Display client data
Console.WriteLine(” client data: “+ strMsg);
}
}
static void Main(string[] args)
{
SocketT obj = new SocketT();
Console.ReadKey();
}
}
}