I. SocketIntroduction Socket is a method of process communication. It calls some API functions of this network library to exchange data between processes distributed on different hosts. Several definitions: (1) IP Address: The network address assigned to the local host according to the TCP/IP protocol. Two processes must communicate with each other. Any process must first know the location of the other party, that is, the IP address of the other party. (2) port number: used to identify a local communication process. A local process occupies a port number during communication. Different Process port numbers are different, therefore, an unaccessed port number must be allocated before communication. (3) connection: the communication link between two processes. (4) Semi-correlation: using a triple in the network can uniquely identify a process in the world: (Protocol, local address, local port number) Such a triple is called a semi-correlation, which specifies each half of the connection. (4) full correlation: a complete inter-network process communication must be composed of two processes and can only use the same high-level protocol. That is to say, it is impossible for one end of the communication to use the TCP protocol, while the other end to use the UDP protocol. Therefore, a complete inter-network communication requires a quintuple: (Protocol, local address, local port number, remote address, and remote port number) Such a quintuple is called association, that is, two half-correlation protocols can be combined into an appropriate correlation, or completely specify to form a connection. 2. Customer/Server Mode In TCP/IP network applications, the main mode of interaction between two processes is the Client/Server (C/S) mode, that is, the customer sends a service request to the server. After receiving the request, the server provides the corresponding service. The customer/Server mode is based on the following two points: (1) first, the reason for establishing a network is that the hardware and software resources, computing power, and information in the network are not equal and need to be shared, so as to provide services to hosts with numerous resources, the non-peering Effect of customer request services with fewer resources. (2) second, inter-network process communication is completely asynchronous. Inter-communication processes do not have a parent-child relationship and do not share the memory buffer, therefore, a mechanism is required to establish a connection between processes that want to communicate with each other and synchronize the data exchange between them. This mechanism is based on the Client/Server mode of TCP/IP. Server: The process is that the server must first start and provide the corresponding services according to the request: (1) Open a channel and inform the local host that it is willing to receive customer requests from a port on a recognized address (for example, port 21 on FTP; (2) Wait for the customer's request to arrive at the port; (3) when receiving a service request from the client, process the request and send a response signal. To receive a concurrent service request, activate a new process to process the request (such as fork and exec in UNIX ). The new process processes this customer request and does not need to respond to other requests. After the service is completed, close the communication link between the new process and the customer and terminate the process. (4) return step (2) and wait for another customer's request. (5) disable the server Client: (1) Open a channel and connect to the specific port of the host where the server is located; (2) Send a service request message to the server, wait for and receive the response; Continue to make the request ...... (3) Close the communication channel and terminate the request. We can see from the process described above: (1) The role of client and server processes is asymmetric, so the code is different. (2) server processes are generally started first. As long as the system is running, the service process persists until it is normal or forced to terminate. After introducing the basic knowledge, the following describes some API functions: Create socket -- socket () Before using a socket, an application must first have a socket. The system calls socket () to provide the application with the means to create a socket. The call format is as follows: Socket Pascal far socket (int af, int type, int Protocol ); This call receives three parameters: AF, type, and protocol. The AF parameter specifies the region where the communication occurs: af_unix, af_inet, af_ns, and so on. In DOS and Windows, only af_inet is supported, which is the region of the Internet. Therefore, the address family is the same as the protocol family. The type parameter describes the type of the socket to be created. There are three types: (1) TCP streaming socket (sock_stream) provides a connection-oriented and reliable data transmission service. Data is sent without errors and repeat, and received in the sending order. Internal traffic control to avoid data flow exceeding the limit. Data is considered as a byte stream with no length limit. The file transfer protocol (FTP) uses a streaming socket. (2) The datagram socket (sock_dgram) provides a connectionless service. Data packets are sent in the form of independent packets. No error guarantee is provided. data may be lost or duplicated, and the receiving order is disordered. Network File System (NFS) uses a datagram socket. (3) 3. original socket (sock_raw) This interface allows direct access to lower-layer protocols, such as IP and ICMP. It is often used to verify new protocol implementations or access new devices configured in existing services. The Protocol Parameter indicates the specific protocol used by the socket. If the caller does not want to specify the protocol, the value is set to 0 and the default connection mode is used. Create a socket based on the three parameters, allocate the corresponding resources to it, and return an integer socket number. Therefore, the socket () System Call actually specifies the "protocol" dollar in the related quintuple. Specify the local address -- BIND () After a socket is created with socket (), a namespace (address family) exists, but it is not named. BIND () associates the socket address (including the local host address and local port address) with the created socket number, that is, assign the name to the socket to specify the local semi-correlation. The call format is as follows: Int Pascal far BIND (socket S, const struct sockaddr far * Name, int namelen ); The parameter S is the socket Descriptor (socket number) returned by the socket () call and not connected ). The parameter name is the local address (name) assigned to socket S. Its length is variable and the structure varies with the communication domain. Namelen indicates the name length. If no error occurs, BIND () returns 0. Otherwise, socket_error is returned. Establish a socket connection -- connect ()And accept () These two system calls are used to complete a complete related establishment, and connect () is used to establish a connection. Accept () is used to make the server wait for the actual connection from a customer process. The call format of Connect () is as follows: Int Pascal far connect (socket S, const struct sockaddr far * Name, int namelen ); The parameter S is the local socket descriptor to establish a connection. The parameter name indicates the pointer indicating the structure of the socket address of the other party. The length of the socket address of the other party is described by namelen. If no error occurs, connect () returns 0. Otherwise, socket_error is returned. In the connection-oriented protocol, this call causes the actual connection between the local system and the external system. Because the address family is always included in the first two bytes of the socket address structure, and is related to a protocol family through socket () calls. Therefore, the BIND () and connect () protocols are not required as parameters. The call format of accept () is as follows: Socket Pascal far accept (socket S, struct sockaddr far * ADDR, int far * addrlen ); The parameter S is the local socket descriptor. You must call listen () before using the parameter called by accept (). The ADDR pointer to the client's socket address structure to receive the address of the connected object. The exact ADDR format is determined by the address family created at the socket creation. Addrlen is the length (in bytes) of the client socket address ). If no error occurs, accept () returns a socket type value, indicating the descriptor of the received socket. Otherwise, the returned value is invalid_socket. Accept () is used for connecting servers. The ADDR and addrlen parameters store the customer's address information. Before the call, the ADDR parameter points to an address structure with an empty initial value, while the initial value of addrlen is 0. After the accept () is called, the server waits for the customer connection request to be received from the socket number S, and the connection request is sent by the customer's connect () call. When a connection request arrives, the accept () call puts the first client socket address and length in the request connection queue into ADDR and addrlen, create a new socket number with the same features as S. The new socket can be used to process concurrent requests from the server. Four socket system calls, socket (), BIND (), connect (), accept (), can complete a fully quintuple-related establishment. Socket () specifies the Protocol element in the quintuple. Its usage has nothing to do with whether it is a customer or server or connection-oriented. BIND () specifies the Local Binary In the quintuple, that is, the address and port number of the local host. Its usage is related to whether connection is oriented, BIND () must be called. If connection orientation is adopted, BIND () can be called instead of Connect. If no connection is used, the customer must use bind () to obtain a unique address. Listener ── listen () This call is intended for connection servers, indicating that it is willing to receive connections. Listen () must be called before accept (). The call format is as follows: Int Pascal far listen (socket S, int backlog ); The parameter S identifies a locally established, unconnected socket number, and the server is willing to receive requests from it. Backlog indicates the maximum length of the Request connection queue. It is used to limit the number of requests in the queue. Currently, the maximum value is 5. If no error occurs, listen () returns 0. Otherwise, it returns socket_error. During the execution of the call, listen () can complete the required connection for the socket s without calling BIND () and establish a request connection queue with the length of backlog. Calling listen () is the third step in the four steps in which the server receives a connection request. It allocates a stream socket when socket () is called, and calls bind () after giving s a name, and must be called before accept. Data transmission-send ()And Recv () After a connection is established, data can be transmitted. Common system calls include send () and Recv (). The send () call is used to send output data on the connected datagram or stream socket specified by S. The format is as follows: Int Pascal far send (socket S, const char far * Buf, int Len, int flags ); The parameter S is the descriptor of the connected local socket. The Buf pointer to a buffer with sent data. Its length is specified by Len. Flags specifies the transmission control mode, such as whether to send out-of-band data. If no error occurs, send () returns the total number of bytes sent. Otherwise, it returns socket_error. The Recv () call is used to receive input data on the connected datagram or stream socket specified by S. The format is as follows: Int Pascal far Recv (socket S, char far * Buf, int Len, int flags ); The parameter S is the connected socket descriptor. The Buf pointer to the buffer for receiving input data. Its length is specified by Len. Flags specifies the transmission control mode, such as whether to receive out-of-band data. If no error occurs, Recv () returns the total number of bytes received. If the connection is closed, 0 is returned. Otherwise, it returns socket_error. Input/Output multiplexing-select () The Select () call is used to detect the status of one or more sockets. For each socket, this call can request read, write, or error information. The socket set in the given Request status is indicated by an fd_set structure. This structure is updated to reflect the subset of sockets that meet specific conditions. At the same time, the Select () call returns the number of sockets that meet the conditions. The call format is as follows: Int Pascal far select (INT NFDs, fd_set far * readfds, fd_set far * writefds, fd_set far * limit TFDs, const struct timeval far * timeout ); The NFDs parameter indicates the value range of the socket descriptor to be checked. This variable is generally ignored. The readfds parameter points to the pointer to the socket descriptor set for read detection. The caller wants to read data from it. The writefds parameter points to the pointer to the socket descriptor set for write detection. Exceptfds indicates the pointer to the socket descriptor set to detect for errors. Timeout points to the maximum waiting time of the select () function. If it is set to null, the operation is blocked. Select () returns the total number of socket descriptors that have been prepared in the fd_set structure, or returns socket_error if an error occurs. Close socket-closesocket () Closesocket () closes socket S and releases the resources allocated to the socket. If s involves an open TCP connection, the connection is released. Closesocket () is called in the following format: Bool Pascal far closesocket (socket S ); Socket descriptor to be disabled by parameter S. If no error occurs, closesocket () returns 0. Otherwise, socket_error is returned. The above are some common API functions of the socket API. The following is a piece of code: // Client code: # Include <winsock2.h> # Include <stdio. h> # Pragma comment (Lib, "ws2_32.lib ") Int main () { Int err; Word versionrequired; Wsadata; Versionrequired = makeword (1, 1 ); Err = wsastartup (versionrequired, & wsadata); // version information of the Protocol Library If (! Err) { Printf ("the client nested word has been opened! \ N "); } Else { Printf ("An error occurred while opening the nested words on the client! \ N "); Return 0; // end } Socket clientsocket = socket (af_inet, sock_stream, 0 ); Sockaddr_in clientsock_in; Clientsock_in.sin_addr.s_un.s_addr = inet_addr ("127.0.0.1 "); Clientsock_in.sin_family = af_inet; Clientsock_in.sin_port = htons (6000 ); // BIND (clientsocket, (sockaddr *) & clientsock_in, strlen (sockaddr); // pay attention to the third parameter // Listen (clientsocket, 5 ); Connect (clientsocket, (sockaddr *) & clientsock_in, sizeof (sockaddr); // start the connection Char receivebuf [100]; Recv (clientsocket, receivebuf, 101,0 ); Printf ("% s \ n", receivebuf ); Send (clientsocket, "Hello, this is client", strlen ("Hello, this is client") + 1, 0 ); Closesocket (clientsocket ); Wsacleanup (); Return 0; } //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /////////////////// // Server code: # Include <winsock2.h> # Include <stdio. h> # Pragma comment (Lib, "ws2_32.lib ") Int main () { // Create a socket Word myversionrequest; Wsadata; Myversionrequest = makeword (1, 1 ); Int err; Err = wsastartup (myversionrequest, & wsadata ); If (! Err) { Printf ("opened socket \ n "); } Else { // Bind the socket further Printf ("the nested word is not opened! "); Return 0; } Socket sersocket = socket (af_inet, sock_stream, 0); // creates an identifiable socket // Parameters to be bound Sockaddr_in ADDR; ADDR. sin_family = af_inet; ADDR. sin_addr.s_un.s_addr = htonl (inaddr_any); // ip address ADDR. sin_port = htons (6000); // bind the port BIND (sersocket, (sockaddr *) & ADDR, sizeof (sockaddr); // The binding is complete. Listen (sersocket, 5); // The second parameter indicates the maximum number of connections that can be received. //////////////////////////////////////// ////////////////////////////////// // Start listening //////////////////////////////////////// ////////////////////////////////// Sockaddr_in clientsocket; Int Len = sizeof (sockaddr ); While (1) { Socket serconn = accept (sersocket, (sockaddr *) & clientsocket, & Len); // if it is not accept, it is conection .. It will constantly listen Char sendbuf [100]; Sprintf (sendbuf, "Welcome % s to Bejing", inet_ntoa (clientsocket. sin_addr); // find the corresponding IP address and print this line to it Send (serconn, sendbuf, strlen (sendbuf) + 1, 0 ); Char receivebuf [100]; // receives Recv (serconn, receivebuf, strlen (receivebuf) + 1, 0 ); Printf ("% s \ n", receivebuf ); Closesocket (serconn); // close Wsacleanup (); // actions to release resources } Return 0; } |