C # Socket and implementation

Source: Internet
Author: User
C # Socket

Microsoft. net Framework provides applications with hierarchical, scalable, and governed network services to access the Internet. Its namespace is System. net and System. net. sockets contains a variety of classes to develop a variety of network applications .. . Net class uses a layered structure that allows applications to access the network at different control levels. developers can choose to compile programs at different levels as needed, these levels cover almost all the needs of the Internet-from socket sockets to common requests/responses. More importantly, this layer can be expanded to meet the needs of continuous Internet expansion.

Aside from the layer-7 architecture of the ISO/OSI model, we can look at the logic layer of the TCP/IP model ,. net class can be considered to contain three layers: Request/response layer, application protocol layer, and transmission layer. WebReqeust and WebResponse represent the request/response layer. Classes supporting Http, Tcp, and Udp constitute the application protocol layer, while the Socket class is in the transmission layer. It can be illustrated as follows:

It can be seen that the transport layer is at the bottom of this structure. When the application protocol layer and request/response layer above it cannot meet the special needs of the application, you need to use this layer for Socket programming.

In. Net, the System. Net. Sockets namespace provides a managed implementation of the Windows Sockets (Winsock) interface for developers who need to strictly control network access. System. all other network protocol classes in the. Net namespace are built on the Socket implementation. For example, TCPClient, TCPListener, and UDPClient encapsulate detailed information about TCP and UDP connections created to the Internet; the NetworkStream class provides basic data streams for network access. Many common Internet services can see Socket traces, such as Telnet, Http, Email, and Echo, despite the different definitions of the communication Protocol, the basic transmission of these services uses sockets.

In fact, the Socket can be considered as a data channel like a Stream. This channel is set up between the application end (client) and the remote server end, and then reads (receives) data) and write (send) for this channel.

It can be seen that after a Socket object is created on the application or server, you can use the Send/SentTo method to Send data to the connected Socket, alternatively, use the Receive/ReceiveFrom method to Receive data from the connected Socket;

For Socket programming, the Socket class of the. NET Framework is the managed code version of the Socket service provided by the Winsock32 API. A large number of methods are provided for network programming. In most cases, the Socket class method only sends data to their local Win32 copies and handles any necessary security checks. If you are familiar with Winsock API functions, it will be very easy to write network programs using the Socket class. Of course, if you have never been in touch with it, it will not be too difficult. Follow the instructions below, you will find that there are rules to develop windows network applications using the Socket class, which follow roughly the same steps in most cases.

Before using it, you must first create an instance of the Socket object, which can be achieved through the Socket class constructor:

Public Socket (AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType );

The addressFamily parameter specifies the addressing scheme used by the Socket, The socketType parameter specifies the Socket type, and the protocolType parameter specifies the protocol used by the Socket.

The following example creates a Socket that can be used for communication over TCP/IP-based networks (such as the Internet.

Socket s = new Socket (AddressFamily. InterNetwork, SocketType. Stream, ProtocolType. Tcp );

To use UDP instead of TCP, you need to change the protocol type, as shown in the following example:

Socket s = new Socket (AddressFamily. InterNetwork, SocketType. Dgram, ProtocolType. Udp );

Once a Socket is created on the client, you can Connect to the specified server through the Connect method and Send data to the remote server through the Send/SendTo method, then, you can use Receive/ReceiveFrom to Receive data from the server. on the server side, you need to Bind the specified interface using the Bind method to associate the Socket with a local endpoint, the Listen method is used to Listen for requests on this interface. When listening for a connection to the user end, the Accept is called to complete the connection operation, and a new Socket is created to process incoming connection requests. After using the Socket, remember to use the Shutdown method to disable the Socket and use the Close method to Close the Socket. The methods/functions used in this process include:

Socket. Connect Method: establish a connection to a remote device
Public void Connect (EndPoint remoteEP) (with overload method)
Socket. Send method: sends data to the connected Socket starting from the indicated position in the data.
Public int Send (byte [], int, SocketFlags); (there are overload methods)
The Socket. SendTo method sends data to a specific endpoint.
Public int SendTo (byte [], EndPoint); (there are overload methods)
Socket. Receive method: receives data from the connected Socket to a specific location in the receiving buffer.
Public int Receive (byte [], int, SocketFlags );
Socket. ReceiveFrom method: receives data from a specific location in the data buffer and stores the endpoint.
Public int ReceiveFrom (byte [], int, SocketFlags, ref EndPoint );
Socket. Bind method: Associate the Socket with a local endpoint:
Public void Bind (EndPoint localEP );
Socket. Listen method: place the Socket in the listening state.
Public void Listen (int backlog );
Socket. Accept method: Create a new Socket to process incoming connection requests.
Public Socket Accept ();
Socket. Shutdown method: Disable sending and receiving on a Socket
Public void Shutdown (SocketShutdown how );
Socket. Close method: Force Socket connection to Close
Public void Close ();

As you can see, the preceding methods contain EndPoint parameters. On the Internet, TCP/IP uses a network address and a service port number to uniquely identify the device. The network address identifies a specific device on the network, and the port number identifies a specific service on the device to be connected. The combination of network addresses and service ports is called an endpoint. in the. NET Framework, the EndPoint class indicates the EndPoint. It provides an abstraction that represents network resources or services and marks network addresses and other information .. Net also defines the child of an EndPoint for each supported address family. For an IP address family, this class is IPEndPoint. The IPEndPoint class contains the host and port information required by the application to connect to the service on the host. The IPEndPoint class forms a connection point to the service by combining the Host IP address and port number of the service.

When using the IPEndPoint class, it inevitably involves the computer ip address. There are two types of. Net IP address instances:

IPAddress: The IPAddress class contains the IP address of the computer on the IP network. The Parse method can convert an IP address string to an IPAddress instance. The following statement creates an IPAddress instance:

IPAddress myIP = IPAddress. Parse (" ");

Dns: Provides domain name services to applications that use TCP/IP Internet services. Its Resolve method queries DNS servers to map user-friendly Domain Names (such as "host.contoso.com") to digital Internet addresses (such as ). The Resolve method returns an IPHostEnty instance that contains a list of the addresses and aliases of the requested names. In most cases, you can use the first address returned in the AddressList array. The following code obtains an IPAddress instance that contains the IP address of host.contoso.com.

IPHostEntry ipHostInfo = Dns. Resolve ("host.contoso.com ");
IPAddress ipAddress = ipHostInfo. AddressList [0];

You can also use the GetHostName method to obtain the IPHostEntry instance:

IPHosntEntry hostInfo = Dns. GetHostByName ("host.contoso.com ")

When using the preceding methods, you may need to handle the following exceptions:

SocketException exception: the operating system error occurs when the Socket is accessed.

ArgumentNullException exception: the parameter is null.

ObjectDisposedException exception: the Socket has been closed.

After learning the above knowledge, the following code combines the IP address and port number of the server host (host.contoso.com) to create a remote endpoint for the connection:

IPEndPoint ipe = new IPEndPoint (ipAddress, 11000 );

After the address of the remote device is determined and the port used for connection is selected, the application can try to establish a connection with the remote device. The following example uses an existing IPEndPoint instance to connect to a remote device and capture Possible exceptions:

Try {
S. Connect (ipe); // try to Connect
// An exception occurred when the processing parameter is null.
Catch (ArgumentNullException AE ){
Console. WriteLine ("ArgumentNullException: {0}", AE. ToString ());
// Handle operating system exceptions
Catch (SocketException se ){
Console. WriteLine ("SocketException: {0}", se. ToString ());
Catch (Exception e ){
Console. WriteLine ("Unexpected exception: {0}", e. ToString ());

You need to know that the Socket class supports two basic modes: synchronous and asynchronous. The difference is that in synchronous mode, the call to the function that executes network operations (such as Send and Receive) will not return the control to the caller until the operation is complete. In asynchronous mode, these calls return immediately.

In addition, in many cases, Socket programming is implemented on the client and server based on different situations, and the application program is compiled on the client to send requests to the specified port on the server, at the same time, the preparation of the server application to process the request has been mentioned in the above description; of course, not all Socket programming requires you to strictly write these two programs; depending on the application situation, you can construct a request string on the client. The corresponding port of the server captures the request and submits it to its public service program for processing. The string in the following example sends a page request to the remote host:

String Get = "GET/HTTP/1.1 \ r \ nHost:" + server + "\ r \ nConnection: Close \ r \ n ";

After the specified port of the remote host receives this request, it can use its public service program for processing without the need to compile server applications separately.

Using the knowledge of using Visual C # For Socket network program development described above, the program section below fully implements the Web page download function. You only need to enter the remote host name (Dns host name or IP address in four-part notation separated by dots) and the pre-saved local file name on the form, the remote host page can be obtained and saved in the specified file on the local machine by using port 80 that provides the Http service. If the format is .htm, you can open the page in an Internet browser. Add code as appropriate, and you can even implement a simple browser program.

The main source code for implementing this function is as follows:

// "Start" button event
Private void button#click (object sender, System. EventArgs e ){
// Obtain the pre-saved file name
String fileName = textBox3.Text. Trim ();
// Remote host
String hostName = textBox1.Text. Trim ();
// Port
Int port = Int32.Parse (textBox2.Text. Trim ());
// Obtain host information
IPHostEntry ipInfo = Dns. GetHostByName (hostName );
// Obtain IPAddress []
IPAddress [] ipAddr = ipInfo. AddressList;
// Obtain the ip address
IPAddress ip = ipAddr [0];
// Combine remote endpoints
IPEndPoint hostEP = new IPEndPoint (ip, port );
// Create a Socket instance
Socket socket = new Socket (AddressFamily. InterNetwork, SocketType. Stream, ProtocolType. Tcp );
// Try to connect
Socket. Connect (hostEP );
Catch (Exception se)
MessageBox. Show ("connection error" + se. Message, "prompt Message
, MessageBoxButtons. RetryCancel, MessageBoxIcon. Information );
// Request content string sent to the remote host
String sendStr = "GET/HTTP/1.1 \ r \ nHost:" + hostName +
"\ R \ nConnection: Close \ r \ n ";
// Create a bytes byte array to convert the sending string
Byte [] bytesSendStr = new byte [1, 1024];
// Convert the sent content string to a byte array
BytesSendStr = Encoding. ASCII. GetBytes (sendStr );
// Send a request to the host
Socket. Send (bytesSendStr, bytesSendStr. Length, 0 );
Catch (Exception ce)
MessageBox. Show ("sending error:" + ce. Message, "prompt Message
, MessageBoxButtons. RetryCancel, MessageBoxIcon. Information );
// Declare the string that receives the returned content
String recvStr = "";
// Declare a byte array. The length of data received at a time is 1024 bytes.
Byte [] recvBytes = new byte [1, 1024];
// Returns the actual number of bytes of received content.
Int bytes = 0;
// Read data cyclically until all data is received
While (true)
Bytes = socket. Receive (recvBytes, recvBytes. Length, 0 );
// Exit the loop after reading.
If (bytes <= 0)
// Convert the number of bytes read to a string
RecvStr + = Encoding. ASCII. GetString (recvBytes, 0, bytes );
// Convert the read string to a byte array
Byte [] content = Encoding. ASCII. GetBytes (recvStr );
// Create a file stream object instance
FileStream fs = new FileStream (fileName, FileMode. OpenOrCreate, FileAccess. ReadWrite );
// Write a file
Fs. Write (content, 0, content. Length );
Catch (Exception fe)
MessageBox. Show ("file creation/writing error:" + fe. Message, "prompt Message", MessageBoxButtons. RetryCancel, MessageBoxIcon. Information );
// Disable Socket
Socket. Shutdown (SocketShutdown. Both );
// Close the Socket
Socket. Close ();

The program is successfully debugged in Windows XP Chinese edition,. Net Frameworkd Chinese official edition, and Visual Studio. Net Chinese official edition.
C # Socket program (TCP)

In fact, as long as the Socket connection is used, Thread is basically used, which is cross-used.
C # encapsulation Socket usage is basically not very complicated, but I don't know whether the hosted Socket has any other performance or security issues.
The underlying operation that can be found in C # Is socket. The concept is not explained.
The program model is as follows:
WinForm program: starts port listening, monitors Socket connections, and regularly closes inactive connections;
Listener: process the Socket's Accept function, listen for new connections, and create a new Thread to process these connections ).
Connection: processes the session of each Connection.

1: How does WinForm start a new thread to start Listener:
// Start the server
Private void btn_startServer_Click (object sender, EventArgs e)
// This. btn_startServer.Enabled = false;
Thread _ createServer = new Thread (new ThreadStart (WaitForConnect ));
_ CreateServer. Start ();
// Wait all connections
Private void WaitForConnect ()
SocketListener listener = new SocketListener(Convert.ToInt32(this.txt _ port. Text ));
Listener. StartListening ();
Because the listener connection is a function that waits cyclically, it cannot be directly executed in the WinForm thread. Otherwise, Winform cannot continue any operations, so a new thread is specified to execute this function and start the listener loop.
This new thread is relatively simple. Basically there is no startup parameter, and you can simply specify the processing function.
2: How does Listener start loop listening and start a new thread with parameters to process Socket connection sessions.
First, let's look at how to establish a listener: (StartListening function)
IPEndPoint localEndPoint = new IPEndPoint (_ ipAddress, _ port );
// Create a TCP/IP socket.
Socket listener = new Socket (AddressFamily. InterNetwork, SocketType. Stream, ProtocolType. Tcp );
// Bind the socket to the local endpoint and listen for incoming connections.
Listener. Bind (localEndPoint );
Listener. Listen (20); // 20 trucks

// Start listening for connections.
While (true)
// Here will be susponded while waiting for a new connection.
Socket connection = listener. Accept ();
Logger. Log ("Connect", connection. RemoteEndPoint. ToString (); // log it, new connection
The basic steps are relatively simple:
Create an IPEndPoint object for the local machine to listen on the specified port;
Then bind it to a listening Socket;
Enter the while loop and wait for a new join;
If a new connection exists, create a new socket to correspond to the session of the connection.
It is worth noting that the join code is listener. Accept (). When this sentence is executed, the program waits here until there is a new joint inspection request. This is synchronous execution. Of course, it can also be executed asynchronously.

The new connection Socket is established (after Accept). What should I do with these new sockets? They are still a loop wait, so we still need to create a new Thread to Process sessions (receive/send messages) for these sockets, and this Thread will receive parameters.
Thread itself cannot receive parameters. To enable it to receive parameters, you can define a new class and add parameters as attributes.
Because each Socket is a Connection cycle, I have defined such a class public class Connection. This class has at least one such constructor public Connection (Socket socket). The reason for this is to pass the Socket parameter to the Connection object so that the Listener can start this Thread, thread can know which Socket he is processing.
Specific solution: (in the StartListening function of Listener, ocket connection = listener. Accept)
Connection gpsCn = new Connection (connection );
// Each socket will be wait for data. keep the connection.
Thread thread = new Thread (new ThreadStart (gpsCn. WaitForSendData ));
Thread. Name = connection. RemoteEndPoint. ToString ();
Thread. Start ();
In this way, the new socket runs in the new Thread after the Accept.
3: Connection session Processing
After a new Connection (socket) is established, the remote Connection can be connected to the socket, which is nothing more than send and receive.
Now let's take a look at how to write the Connection. WaitForSendData function run by this thread.
While (true)
Bytes = new byte [1024];
String data = "";
// Wait m will be waiting the msg of receive envet. like Accept ();
// Here will be susponded while waiting for socket income msg.
Int bytesRec = this. _ connection. Receive (bytes );
_ LastConnectTime = DateTime. Now;
If (bytesRec = 0) // close envent
Logger. Log ("Close Connection", _ connection. RemoteEndPoint. ToString ());
Data + = Encoding. ASCII. GetString (bytes, 0, bytesRec );
//....... Handle your data.
The basic process is as follows:
Execute the Receive function to Receive messages sent from remote sockets;
Converts information from byte to string;
Process the information and enter the next loop. Wait until the socket sends new information.
Note the following:
1: Receive function. This function is similar to the Accept function of Listener. Wait for execution in this place. If there is no new message, this function will not execute the next sentence and will remain waiting.
2: receives byte streams and needs to be converted to strings.
3: Determine how to remotely close the connection
4: If the message of the other party is very large, the data must be received cyclically.
4: How to manage these connections (threads)
Through the above program, you can basically establish a listener and process the connection session. But how to manage these threads? Otherwise, thread generation is a disaster.
The management method is relatively simple. In Listener, I defined a static hash table (static public Hashtable Connections = new Hashtable ();) to store the Connection instance and its corresponding Thread instance. A definition of the last join time (private DateTime _ lastConnectTime;) is also added to the connection ;). When a new Connection is established (after the Accept () of Listener), the Connection instance and Thread instance are saved in the hash table; the last Connection time is modified during Connection Receive. In this way, we can know where the Connection is and whether the session is active.
You can manage these sessions in the Winform program and set the timeout value.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.