[Linux network programming] socket detailed explanation

Simple socket communication

#include <sys/socket.h>
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

The first parameter: IP address type, AF_INET means using IPv4, if using IPv6 please use AF_INET6.
The second parameter: data transmission method, SOCK_STREAM means stream format, connection-oriented, mostly used for TCP. SOCK_DGRAM means datagram format, connectionless, mostly used for UDP.
The third parameter: protocol, 0 means automatically deduce the protocol type according to the previous two parameters. Set to IPPROTO_TCP and IPPTOTO_UDP, which represent TCP and UDP respectively.
For the client, the only identifier of the server is an IP address and port. At this time, we need to bind this socket to an IP address and port. First create a sockaddr_in structure

#include <arpa/inet.h>  //这个头文件包含了<netinet/in.h>,不用再次包含了
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));

Then use bzero to initialize this structure, this function is in the header file <string.h> or in. Two guidelines from "Effective C++" are used here:
Item 04: Make sure that the object has been initialized before it is used. If it is not cleared, use the gdb debugger to view the variables in addr, there will be some random values, which may cause unexpected problems in the future.
Item 01: Treat C++ as a language federation. Think of C and C++ as two languages. When writing code, you need to clearly know whether you are writing C or C++. If you are writing C, please include the header file <string.h>. If writing C++, include <cstring>.

设置地址族、IP地址和端口:
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
然后将socket地址与文件描述符绑定:
bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr));

Why use a dedicated socket address (sockaddr_in) when defining and convert it to a general socket address (sockaddr) when binding, and functions such as inet_addr and htons that convert IP addresses and port numbers into network byte order and their necessity in the
game Double "Linux High Performance Server Programming" Chapter 5, Section 1: Socket address API is discussed in detail.
insert image description here
Finally, we need to use the listen function to listen to this socket port. The second parameter of this function is the maximum listening queue length of the listen function. The maximum recommended by the system is SOMAXCONN, which is defined as 128.
listen(sockfd, SOMAXCONN);
To accept a client connection, you need to use the accept function. For each client, we also need to save the client's socket address information when accepting a connection, so there is the following code:

struct sockaddr_in clnt_addr;
socklen_t clnt_addr_len = sizeof(clnt_addr);
bzero(&clnt_addr, sizeof(clnt_addr));
int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len);
printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));

It should be noted that there is a little difference from the third parameter of accept and bind. For bind, only the size of serv_addr needs to be passed in, while accept needs to write the length of the client socket, so a variable of type socklen_t needs to be defined and passed in The address of this variable. In addition, the accept function will block the current program, and the program will not run until a client socket is accepted.

Code: https://github.com/poppynull/WebServer

Guess you like

Origin blog.csdn.net/poppyty/article/details/129375667
Recommended