1. wsastartup Function
Int wsastartup (
Word wversionrequested,
Lpwsadata
);
The program using the socket must call the wsastartup function before using the socket. The first parameter of this function indicates the socket version requested by the program. The high byte indicates the secondary version and the low byte indicates the primary version; the operating system uses the second parameter to return the request's socket version. When an application calls the wsastartup function, the operating system searches for the corresponding socket Library Based on the requested socket version, and then binds the socket Library to the application. In the future, the application can call other socket functions in the requested socket library. After the function is successfully executed, 0 is returned.
For example, if a program uses a socket of Version 2.1, the program code is as follows:
Wversionrequested = makeword (2, 1 );
Err = wsastartup (wversionrequested, & wsadata );
Ii. wsacleanup Function
Int wsacleanup (void );
After the application completes the use of the requested socket library, it needs to call the wsacleanup function to unbind from the socket library and release the system resources occupied by the socket library.
Iii. Socket Functions
Socket socket (
Int AF,
Int type,
Int Protocol
);
The application calls the socket function to create a socket capable of network communication. The first parameter specifies the protocol family used by the application. For the TCP/IP protocol family, this parameter sets af_inet (pf_inet in Linux ); the second parameter specifies the socket type to be created, the stream socket type is sock_stream, the datagram socket type is sock_dgram, and the third parameter specifies the communication protocol used by the application. This function returns the descriptor of the newly created socket if the call is successful, and invalid_socket if the call fails. The socket descriptor is an integer value. Each process has a socket Descriptor Table in the process space, which stores the correspondence between the socket Descriptor and the socket data structure. In this table, one field stores the descriptor of the newly created socket, and the other field stores the address of the socket data structure. Therefore, the corresponding socket data structure can be found based on the socket descriptor. Each process has a socket Descriptor Table in its own process space, but the socket data structure is in the kernel buffer of the operating system. The following is an example of creating a stream socket:
Struct protoent * PPE;
PPE = getprotobyname ("TCP ");
Socket listensocket = socket (af_inet, sock_stream, PPE-> p_proto );
Iv. closesocket Functions
Int closesocket (
Socket s
);
The closesocket function is used to close a socket whose descriptor is S. Each process has a socket Descriptor Table. Each socket descriptor in the table corresponds to a socket Data Structure located in the operating system buffer, therefore, several socket descriptors may point to the same socket data structure. There is a field in the socket data structure that stores the number of times this structure is referenced, that is, how many socket descriptors point to this structure. When the closesocket function is called, the operating system first checks the value of this field in the socket data structure. If it is 1, it indicates that only one socket descriptor points to it, therefore, the operating system first clears the entry corresponding to S in the socket Descriptor Table and releases the socket data structure corresponding to S. If this field is greater than 1, then, the operating system only clears the corresponding table items of S in the socket Descriptor Table, and reduces the number of references to the socket data structure of S by 1.
If the closesocket function is successfully executed, 0 is returned; otherwise, socket_error is returned.
5. Send Function
Int send (
Socket s,
Const char far * Buf,
Int Len,
Int flags
);
Both the client and server applications use the send function to send data to the other end of the TCP connection. The client program generally uses the send function to send requests to the server, while the server uses the send function to send responses to the client program. The first parameter of this function specifies the sender socket descriptor. The second parameter specifies a buffer zone for storing data to be sent by the application. The third parameter specifies the number of bytes of data to be sent; the fourth parameter is usually set to 0. Only the execution process of the send function for Synchronous socket is described here. When this function is called, send first compares the length of the data to be sent Len and the length of the sending buffer of socket s. If Len is greater than the length of the sending buffer of S, the function returns socket_error; if Len is smaller than or equal to the length of the sending buffer of S, send first checks whether the protocol is sending data in the sending buffer of S. If yes, wait for the Protocol to finish sending the data, if the Protocol has not started sending data in the sending buffer of S or there is no data in the sending buffer of S, send will compare the remaining space in the sending buffer of S and Len, if Len is larger than the size of the remaining space, send will wait for the Protocol to finish sending data in the s sending buffer, if Len is smaller than the size of the remaining space, send only copies the data in the Buf to the remaining space (note that it is not sending the data in the sending buffer of S to the other end of the connection, instead, send only copies the data in the Buf to the remaining space in the sending buffer of S ). If the send function successfully copies the data, the actual number of bytes of copy is returned. If an error occurs during sending data copy, the send function returns socket_error; if the network is disconnected when sending data while waiting for the Protocol to send data, the send function also returns socket_error. Note that the send function successfully copies the data in the Buf to the remaining space of the s sending buffer, and then returns the data. However, the data is not necessarily uploaded to the other end of the connection immediately. If a network error occurs during subsequent transmission, the next socket function will return socket_error. (Each socket function except send must wait for the data in the socket sending buffer to be transmitted by the protocol before execution. If a network error occurs while waiting, then the socket function will return socket_error)
Note: In Unix systems, if the network is disconnected when sending data while waiting for the send protocol, the process that calls send receives a sigpipe signal. The process processes the signal by default and terminates the process.
Vi. Recv Functions
Int Recv (
Socket s,
Char far * Buf,
Int Len,
Int flags
);
Both the client and server applications use the Recv function to receive data from the other end of the TCP connection. The first parameter of the function specifies the receiver socket descriptor. The second parameter specifies a buffer zone used to store the data received by the Recv function. The third parameter specifies the length of the Buf; the fourth parameter is usually set to 0. Only the execution process of the Recv function for Synchronous socket is described here. When the application calls the Recv function, the Recv waits for the data in the s sending buffer to be transmitted by the Protocol. If the Protocol encounters a network error when sending data in the s sending buffer, then the Recv function returns socket_error. If no data is in the sending buffer of s or the data is successfully sent by the protocol, the Recv first checks the receiving buffer of socket S, if there is no data in the s receiving buffer or the Protocol is receiving data, the Recv waits until the Protocol receives the data. When the Protocol receives the data, the Recv function copies the data in the s receiving buffer to the Buf (note that the data received by the protocol may be larger than the length of the Buf, in this case, you need to call the Recv function several times to copy the data in the s receiving buffer. The Recv function only copies data, and the real data reception is completed by the Protocol). The Recv function returns the actual number of bytes of the copy. If a Recv error occurs during copy, socket_error is returned. If the Recv function is interrupted while waiting for the Protocol to receive data, 0 is returned.
Note: In Unix systems, if the network is disconnected when the Recv function is waiting for the Protocol to receive data, the process that calls the Recv will receive a sigpipe signal, the process processes this signal by default.
VII. Bind Functions
// Generally, the client does not need to call the BIND () function.
Int BIND (
Socket s,
Const struct sockaddr far * Name,
Int namelen
);
After a socket is created, the data structure of the socket contains a default IP address and a default port number. A service program must call the BIND function to bind an IP address and a specific port number to it. Generally, a customer program does not need to call the BIND function to bind an IP address and a disconnected slogan to its socket. The first parameter of the function specifies the socket descriptor to be bound. The second parameter specifies a sockaddr structure, which is defined as follows:
Struct sockaddr {
U_short sa_family;
Char sa_data [14];
};
Sa_family specifies the address family. For sockets in the TCP/IP protocol family, set af_inet. When binding a socket in the TCP/IP protocol family, we usually use another address structure:
Struct sockaddr_in {
Short sin_family;
U_short sin_port;
Struct in_addr sin_addr;
Char sin_zero [8];
};
Sin_family sets af_inet; sin_port indicates the port number. The sin_addr struct has only one unique field s_addr, indicating the IP address. This field is an integer and is generally used as the inet_addr () function () convert an IP address in string form to an integer of the unsigned long type and then set it to s_addr. Some servers are multi-host machines with at least two NICs. Therefore, when a service program running on such a server binds an IP address to its socket, you can set htonl (inaddr_any) to s_addr, the advantage of this is that the client program can communicate with the service program no matter which network segment. If you only bind a fixed IP address to the socket of the service program running on multiple hosts, then, only the client program that is in the same network segment as the IP address can communicate with the service program. We use 0 to fill the sin_zero array to make the size of the sockaddr_in structure consistent with that of the sockaddr structure. The following is an example of a bind function call:
Struct sockaddr_in saddr;
Saddr. sin_family = af_inet;
Saddr. sin_port = htons (8888 );
Saddr. sin_addr.s_addr = htonl (inaddr_any );
BIND (listensocket, (struct sockaddr *) & saddr, sizeof (saddr ));
8. Listen Functions
Int listen (socket S, int backlog );
A service program can call the listen function to make its stream socket s in the listening state. The stream socket s in the listening status maintains a Client Connection Request queue, which can accommodate a maximum of backlog client connection requests. If the function is successfully executed, 0 is returned. If the function fails to be executed, socket_error is returned.
9. Accept Function
Socket accept (
Socket s,
Struct sockaddr far * ADDR,
Int far * addrlen
);
The service program calls the accept function to retrieve the first client request from the client connection request queue of the stream socket s in the listening state, create a new socket to create a connection channel with the customer socket. If the connection is successful, return the descriptor of the new socket. In the future, the new socket will exchange data with the customer socket; if it fails, invalid_socket is returned. The first parameter of the function specifies the stream socket in the listening state. The operating system uses the second parameter to return the address structure of the newly created socket; the operating system uses the third parameter to return the length of the address structure of the newly created socket. The following is an example of an Accept call:
Struct sockaddr_in serversocketaddr;
Int addrlen;
Addrlen = sizeof (serversocketaddr );
Serversocket = accept (listensocket, (struct sockaddr *) & serversocketaddr, & addrlen );
10. Connect Functions
Int connect (
Socket s,
Const struct sockaddr far * Name,
Int namelen
);
The customer program calls the connect function to connect the customer socket s to the service socket listening on the specific port of the Computer specified by name. If the connection is successful, connect returns 0; if the connection fails, socket_error is returned. The following is an example:
Struct sockaddr_in daddr;
Memset (void *) & daddr, 0, sizeof (daddr ));
Daddr. sin_family = af_inet;
Daddr. sin_port = htons (8888 );
Daddr. sin_addr.s_addr = inet_addr ("133.197.22.4 ");
Connect (clientsocket, (struct sockaddr *) & daddr, sizeof (daddr ));
Example: (programs in Linux ):
// Customer Service Program: Remember that the customer service program does not require the BIND () function.
Int main ()
{
Int sockfd;
Int Len;
Struct sockaddr_un address;
Int result;
Char CH =;
Sockfd = socket (af_unix, sock_stream, 0 );
/* Set up the client interface above, using the af_unix Unix domain Protocol */
Address. sun_family = af_unix;
Strcpy (address. sun_path, "server_socket ");
Len = sizeof (Address );
/* The address of the server set interface created above, including the set interface type and name */
Result = connect (sockfd, (struct sockaddr *) & Address, Len );
If (result =-1 ){
Perror ("Oops: Client1 ");
Exit (1 );
}
/* We tried to establish a connection with the server set interface. Once the connection is successful, we will continue to execute the following Program */
Write (sockfd, & Ch, 1 );
Read (sockfd, & Ch, 1 );
/* If it succeeds, a character will be sent to the server and then the server's answer will be read */
Printf ("char from server = % C/N", CH );
Close (sockfd );
Exit (0 );
}
// Server-side program
Int main ()
{
Int server_sockfd, client_sockfd;
Int server_len, client_len;
Struct sockaddr_un server_address;
Struct sockaddr_un client_address;
Unlink ("server_socket ");
/* Delete an interface with the same name first */
Server_sockfd = socket (af_unix, sock_stream, 0 );
/* The above interfaces are set up, which is unknown at this time */
Server_address.sun_family = af_unix;
Strcpy (server_address.sun_path, "server_socket ");
Server_len = sizeof (server_address );
BIND (server_sockfd, (struct sockaddr *) & server_address, server_len );
Listen (server_sockfd, 5 );
/* Create a listening queue. Wait for the user's Connection Request */
While (1) // enter the infinite loop listener status
{
Char ch;
Printf ("server waiting/N ");
Client_sockfd = accept (server_sockfd, (struct sockaddr *) & client_address, & client_len );
/* Accept the request of one customer */
Read (client_sockfd, & Ch, 1 );
/* Once the connection is established, the client sends a message first, so the server reads the message first */
Ch ++;
Write (client_sockfd, & Ch, 1 );
/* Perform simple processing on the read string and send it back */
Close (client_sockfd );
}
}
// Functions of stdafx. h:
The include files for Windows and MFC are very large. Even if there is a fast processing program, it takes quite a long time to compile the program. Since each. cpp file contains the same include file, it is silly to process these files repeatedly for each. cpp file.
To avoid this waste, Appwizard works with the visual C ++ compiler as follows:
Appwizard creates the stdafx. h file, which contains all the MFC include files required for the current project file. This file can change with the selected options.
Appwizard then creates stdafx. cpp. This file is usually the same.
Then Appwizard creates the project file, so that the first compiled file is stdafx. cpp.
When Visual C ++ compiles the stdafx. cpp file, it stores the result in a file named stdafx. PCH. (The extension PCH indicates the precompiled header file .)
When Visual C ++ compiles each subsequent. cpp file, it reads and uses the. PCH file it just generated. Visual c ++ no longer analyzes Windows include files unless you have compiled stdafx. cpp or stdafx. h.