1, Create socket
socket is a readable, writable, controllable and closable file descriptor (integer number)
// Function prototype int socket(int domain, int type, int protocol) //Parameter interpretation domain: Specifies the protocol used by the system. Can be TCP/IP Protocol family, or UNIX Protocol family. The corresponding values are PF_INET(IPv4)/PF_INET6(IPv6) and PF_UNIX. type: Indicates the type of service, including streaming service and datagram service. The corresponding parameters are SOCK_STREAM,SOCK_UGRAM. about TCP/IP For the protocol family, TCP It is based on byte stream, so the transport layer uses TCP,that type To set to. SOCK_STREAM. UDP Is a datagram based protocol, so type The value of corresponds to SOCK_UGRAM. protocol:It indicates the protocol that can be selected under the filtering of the first two parameters. Generally, the value is unique. In all cases, this value is set to 0, indicating the default protocol. return: socket Call success returns a socket File descriptor. Failure Return-1,And set errno.
2, Named socket
When you create a socket and specify which protocol to use, you specify the address family. However, no specific socket address in the address family is specified. Here, we can understand that our kernel is divided into several protocol families, such as TCP/IP protocol family and UNIX protocol family. Each protocol family has many sockets. Each socket is uniquely identified by a specific address. Of course, each socket contains corresponding (all protocol services under TCP/IP and UNIX protocol family).
Binding a socket to the socket address is called naming the socket. In the general server program, the socket should be named. However, the client generally does not need to name the socket. The client generally uses the anonymous method and uses the os to automatically allocate the socket address.
The function bind() needs to be called to name the socket.
//Function prototype int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen) //Parameter interpretation take my_addr Pointer pointing socket Assign to sockfd File descriptor, addrlen refer to socket The length of the address. return: 0 is returned for address binding success and 0 is returned for failure-1,And set errno. errno The value of can be EACCES,EADDRINUSE,EACCES Indicates that the specified address is a protected address, and there are only super addresses Level users can access, EADDRINUSE Represent this socket The address is in use.
Note that the most important point in the above naming process is the socket address. The creation of socket address is described in detail below.
2. 1 general socket address structure
struc sockaddr { sa_family_t sa_family; char sa_data[14]; } //sa_data stores the address value of socket. //sa_family_t is the address family type, sa_family is an address family type variable. //The address family type should correspond to the protocol family type one by one. //For example, in the above socket function, the parameter domain is set to use the PF corresponding to IPv4 in the TCP/IP protocol family_ INET, then the address family here should be set to AF_INET. //You can set according to the following table to achieve one-to-one correspondence.
protocol family | Address family |
---|---|
PF_UNIX | AF_UNIX |
PF_INET | AF_INET |
PF_INET6 | AF_INET6 |
But because like PF_ The address length of UNIX is 108 bytes, PF_ The length of INET is 6 bytes, PF_ The Unit6 address is 26 bytes long, SA_ Data cannot satisfy the address value of the protocol address family. Therefore, a new socket address structure is created under Linux.
struc sockaddr_storage { sa_family_t sa_family; unsigned long int __ss_align; char __ss_padding[128-sizeof(__ss_align)]; } //This ensures sufficient memory to store address space, and__ ss_align ensures memory alignment.
2. 2. Dedicated socket address
The above socket structure has only the address option. To obtain the corresponding IP address, you need to perform the corresponding bit operation. Therefore, Linux establishes a dedicated socket address to facilitate the acquisition of IP address and port number.
For example, the socket address structure of IPv4 is as follows:
struct socketaddr_in { sa_family_t sa_family; //The value of address family IPv4 is AF_INET u_int6_t sin_port; //Port number, where network bytecode identification is used (big end mode) struct in_addr sin_addr; //IPv4 address structure }; struct in_addr { u_int32_t s_addr; //Network bytecode identification (big end mode) is used here };
In addition, there is a corresponding special structure for IPv6 socket address, which is similar to IPv4. The port number and IP address are displayed. Note that the port number and IP address here are network bytecode identification, that is, big end mode.
3, Listening socket
Because the server has to process the requests of multiple clients, it cannot always process them. Therefore, a queue should be established to store the connections in the queue and process them in turn. Therefore, it is necessary to always listen to the client's request connection, and then reasonably process the client's request connection.
//Function prototype int listen(int sockfd,int backlog) //Parameter interpretation sockfd Specify the monitored socket,backlog Parameter indicates the maximum length of the kernel listening queue. identification socket Fully connected socket Quantity, typical value is 5. //listen returns 0 successfully, returns - 1 if it fails, and sets the errno value.
4, Accept connection
Receive a connection from the listening queue
//Function prototype int accept(int sockfd,struct sockaddr* addr, socklen_t * addrlen) //Parameter interpretation sockfd Specify the monitored socket,addr Is to get the remote end of the received connection socket Address, addrlen Remote specified socket The length of the address. //When accept succeeds, a new connection socket is returned. The socket uniquely identifies the accepted connection. The server can communicate with the client by reading and writing the socket. If accept fails, return - 1 and set errno.
5, Summary
A complete process of socket programming on the server side:
->Create socket (specify the protocol to be used, TCP/IP or UNIX protocol, and then refine TCP and UDP)
->Create a socket address (IPv4, IPv6. Note that the port number and IP address should be converted to the network byte order integer)
->Name the socket (bind the socket and socket address, using the bind function)
->Socket listening (listening to client requests, using the listen function)
->The accept function receives the connection and gets a new connection socket. The server can read and write with the remote client.