Using sockets to implement TCP/IP protocol communication

Source: Internet
Author: User
Tags getstream

First, the principle:

First of all, to understand the basic principle of 2 computers to achieve TCP communication, first of all to establish a connection, here to mention the server side and the client, two of the difference between the active and passive relationship, two people dialogue, it is definitely first someone to initiate the session, or who do not speak, talk about what topic, hehe. The same, TCPIP to establish a connection must first have a server, it is passive, it can only wait for others to establish a connection with it, they will not go to the active connection, the client how to connect it, here mentioned 2 things, IP address and port number, popular speaking is you go to visit someone, Know his address is the First Avenue 2nd building, this is the IP address, then 1th building so many number how to distinguish, um. The number is the port (mentioned here, when we visit the Web page is also the IP address and port number, ie the default port number is 80, a server can accept the connection of multiple clients, but a client can only connect a server, after the connection, the server automatically divides the memory area to allocate each client's communication , then, so many client servers how to differentiate, you may say, according to IP, not very complete, very simple example, you a computer open 3 QQ, server how to distinguish. So accurate is the IP and port number, but the client's port number is not determined by your own, is automatically allocated by the computer, otherwise there will be a port conflict, said so much, look at the following picture is simple and clear.


In the above picture, you can understand that program A and program B are 2 socket programs, server-side program a sets the port to 81, has received the connection to 3 clients, computer C opened 2 programs, connected to E and D respectively, and his port is automatically assigned by the computer, connected to the port of E to 789, The connection to D is 790.

After understanding the basic structure of TCPIP communication, then explain the established process, first of all, I use the development environment is visual Studio2008 version, language C #, Component System.Net.Sockets, the establishment of the process includes server-side establishment and client establishment, as shown in the figure:




Second, to achieve:


1. Client:


The first step is to create a client object TcpClient (namespace in System.Net.Sockets), then invoke the method under the object BeginConnect to try to connect, there are 4 entry parameters, address (destination IP), port ( Target port number, Requestcallback (callback function after successful connection), state (pass parameter, is an object, anything, I suggest to pass the TcpClient), call over this function, the system will try to connect to the server.

      The second step, in the first step, is to talk about an entry parameter requestcallback (the callback function after a successful connection), such as we define a function void connected (IAsyncResult  result), after connecting the server successfully, the system will call this function, in the function, we want to get to the system allocated data stream Transfer object (NetworkStream), this object is used to handle the client and server-side data transfer, this object is obtained by tcpclient , in the first step, the entry parameter state, if we pass the tcpclient in, then, in the function we can get it by the entry parameter state and cast it tcpclient tcpclt =  ( TcpClient) result. AsyncState, then gets the data stream transfer object NETWORKSTREAM NS = TCPCLT. GetStream (), this object I recommend to make global variables for other function calls, and then we will suspend the data to receive the wait, call the NS method BeginRead, there are 5 entry parameters, buff (data buffering), offset (buffer starting serial number), size (buffer length ), callback (the return function after receiving the data), state (pass the parameter, just like anything, suggest to pass the buff), after the function is called, you can wait for the data to receive, here because the NetworkStream object has been created, So you can also send data to the server operation, call the NS method write can send data to the server, entry Parameters 3, buff (data buffering), offset (buffer starting serial number), size (buffer length).

The third step, in the second step, is to say that an entry parameter called the BeginRead function callback (the callback function after the data is received), for example, we define a function void Datarec (IAsyncResult result) after the server sends data to the client , the system will call this function, in the function we want to get the data stream (byte array), in the previous step to explain the BeginRead function, there is also an entry parameter state, if we pass the buff in, then, here we are better to convert to byte[] type byte[] Data= (byte[]) result. AsyncState, after the conversion is complete, we also want to get the size of the buffer int length = ns. EndRead (Result), NS is the NetworkStream global object that was created in the previous step, and then we can process the data if the obtained length is 0 to indicate that the client has disconnected.

Concrete implementation code, where I created a class called Test:

Usingsystem;
Using System.Collections.Generic;
Using System.Net.Sockets;  Namespace Test {public class Test {protected TcpClient tcpclient = null; Global client Object protected NetworkStream NetworkStream = null;//Global Data Flow Transport object///<summary>///remote server Connection///</summary>///<param name= "IP" >ip address </param>///<param name= "Port" &G
            t; Port </param> public Test (string IP, int port) {networkstream = null;  TcpClient = new TcpClient (); Object into an entity tcpclient.  BeginConnect (System.Net.IPAddress.Parse (IP), port, new AsyncCallback (Connected), tcpclient); Start the attempt to connect}///<summary>///send data///</summary>///<param Name 
                  = "Data" > Data </param> public void SendData (byte[] data) {if (NetworkStream!= null) NetworkStream. Write (data, 0, data.  Length);
      Sending data to the server  ///<summary>///shutdown///</summary> public void Close () { NetworkStream. Dispose (); Releases the data stream Transfer object tcpclient. Close (); Close connection}///<summary>///shutdown///</summary>///<param name= "Resul T "> Incoming parameter </param> protected void Connected (IAsyncResult result) {TcpClient TCPCLT = (tcpclient) result.  asyncstate; Casts the passed argument to TcpClient NetworkStream = tcpclt.  GetStream ();  Gets the data stream transmission Object byte[] data = new byte[1000]; New buffer NetworkStream for transport. BeginRead (data, 0, 1000, new AsyncCallback (DATAREC), data); Pending receipt of data///<summary>///data receive delegate function///</summary>///<param Name= "Result" > incoming parameter </param> protected void Datarec (IAsyncResult result) {int Leng th = NetworkStream.  EndRead (result);
 Gets the length of the received data               list<byte> data = new list<byte> (); New byte array data. AddRange ((byte[]) result. asyncstate); Gets data. RemoveRange (length, data. Count-length); Remove invalid data based on length byte[] data2 = new byte[1000]; Redefine the receive Buffer networkstream.  BeginRead (data2, 0, 1000, new AsyncCallback (Datarec), data2); Re-suspend receipt wait//custom code area for data processing data if (length = 0) {// Connection has been closed}}}

2. Server-side:

compared to the implementation of the client, the server side of the implementation is slightly more complex, because previously said, a server can accept the N-client connection, so, on the server side, it is necessary for each connected to the client to register, so the server-side program structure includes 2 program structure, The first program structure is primarily responsible for starting the server, registering and revoking visiting clients, so we need to create 2 classes.

     The first program structure is responsible for server startup and client connection registration, first set up TcpListener network listening class, the establishment of the constructor includes localaddr and Port2 parameters, LOCALADDR refers to the local address, which is the IP address of the server, and some people ask why it does not automatically obtain the address of this machine. For this very simple example, the server installed 2 network cards, there are 2 IP addresses, that the establishment of the server can choose to listen to the use of which network port, but the general computer only one network port, You can simply write a fixed function directly to get the IP address System.Net.Dns.GetHostAddresses (System.Net.Dns.GetHostName ()) [0], Gethostaddresses function is to obtain the local IP address, the default selection of the first port then add a [0], the 2nd parameter port is really listening to the ports, this simple, the decision, if there is a port conflict, the function itself will remind the wrong. Step two, start the server, Tcplistener.start (). The third step is to start the client's attempt to connect, Tcplistener.beginaccepttcpclient, entry 2 parameters, callback (the callback function after the client connection), state (transfer parameters, as described in the second section, anything can, Set the TcpListener itself to pass the past), step fourth, set up the callback function after the client connects, for example, we build a function called Void clientaccept (iasyncresult result), the function, We're going to get the client object, and in the third step we pass the TcpListener parameter in, where we get it tcplistener tcplst =  (TcpListener) result through the entry parameter. AsyncState, gets the client object tcpclient bak_tcpclient = tcplst. Endaccepttcpclient (Result), this bak_tcpclient I propose to set up a list in the class, and then add it, because the next client is connected to the object will be washed out, after the client has finished processing, Next we want to start the next client connection Tcplst. Beginaccepttcpclient (New asynccallback (sub_clientaccept),  tcplst, this is the same as the third step, and I will not repeat it.

The second program structure is primarily responsible for individual client and server-side handlers, mainly responsible for data communication, the method is similar to the client code, the basic Datong, in addition to not need to start the connection function, so this program structure mainly start the data listening function, judge the function of disconnection, the function of data send, In the first program, step fourth, we get the client object Bak_tcpclient, where we first start the data listening function NetworkStream ns= bak_tcpclient. GetStream (); NS. BeginRead (data, 0, 1024, new AsyncCallback (DATAREC), data); This is exactly the same as what I introduced in the second section (the 10th line in section II), the processing function of the data, the function to send, The code that determines that the connection has been disconnected is exactly the same as the second section, but here we need to add a piece of code, when we know that the connection has been disconnected, we want to inform the client of the first program structure to delete the client operation, this method I implement is in the creation of a second program structure, When the first program structure is passed in to determine that the connection is disconnected, a public method of the first program structure is invoked to remove the object from the client list.

The first program structure we define a Tsever class, the second program structure we a TClient class, the code is as follows:

public class Tsever {public list<tclient> Clients = new list<tclient> ();  Client List private TcpListener TcpListener = null; Listening Objects///<summary>///Constructors///</summary>///<param name= "Port" > Listening port </param> public tsever (int port) {TcpListener = new TcpListener (System.Net.Dns.GetHostA  Ddresses (System.Net.Dns.GetHostName ()) [0], Port); Start listening TcpListener. Start (); Start listening TcpListener. Beginaccepttcpclient (New AsyncCallback (clientaccept), TcpListener); Start attempting client's connection} private void clientaccept (IAsyncResult result) {TcpListener Tcplst = ( TcpListener) result.
            asyncstate; TcpClient bak_tcpclient = Tcplst.
            Endaccepttcpclient (result);
            TClient bak_client = new TClient (bak_tcpclient, this);
            Clients.add (bak_client); Tcplst. Beginaccepttcpclient (New AsyncCallback (clientaccept), tcplst);  } public class TClient {private TcpClient tcpclient = null;  Client Object Private NetworkStream NetworkStream = null;  Data sending object private Tsever m_parent=null; Parent class///<summary>///constructor///</summary>///<param Name = "TCPCLT" > Client object </param>///<param name= "parent" > Parent </param> public tclient (Tc
                    Pclient TCPCLT, Tsever parent) {this.tcpclient = TCPCLT;
                    This.m_parent = Parent; String IP = ((ipendpoint) tcpclient. Client.remoteendpoint). Address.tostring (); Gets the client IP string port = (IPEndPoint) tcpclient. Client.remoteendpoint).  Port.tostring (); Gets the client port This.networkstream = tcpclt.  GetStream ();
                    Get data Transfer object byte[] data = new byte[1024]; This.networkstream.BeginRead (data, 0, 1024,New AsyncCallback (DATAREC), data),//Start the Listener///<summary>///Data reception </summary>///<param name= "result" ></param> private void Datarec (Iasyncresu Lt result) {int length = NetworkStream.
                    EndRead (result);
                    list<byte> data = new list<byte> (); Data. AddRange ((byte[]) result.
                    asyncstate);
                    byte[] data2 = new byte[1024]; NetworkStream.
                    BeginRead (data2, 0, Maxrec, new AsyncCallback (Datarec), data2);  if (length = = 0) {m_Parent.Clients.Remove (this); Tell the parent class to delete this client} else {data. RemoveRange (length, data.
                         Count-length); Data processing code Data}///<summary>///Send data///</summary>///<param name= "Data" > Database </param>///<retu Rns></returns> public bool SendData (byte[] data) {NetworkStream. Write (data, 0, data.
                Length);
            return (true);
 }
        }

Excerpt from: HTTP://HI.BAIDU.COM/DES_SKY/ITEM/A12969C83801ACBC0D0A7BB2


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.