Socket
The socket is an abstraction layer between the application layer and the transport layer, which abstracts the complex operations of the TCP/IP layer into a few simple interfaces to provide a layer to invoke the implemented process to communicate in the network.
Socket originated from UNIX, in Unix everything is file philosophy, socket is an "open-read/write-off" mode implementation, the server and the client maintain a "file", after establishing a connection open, you can write to their own files for the other side to read or read the contents of the other side, Closes the file at the end of the communication.
Socket type
There are 3 types of sockets commonly found below. (1) streaming socket (SOCK_STREAM) streaming sockets provide reliable, connection-oriented traffic flow, which uses the TCP protocol to ensure the correctness and sequencing of data transmission. (2) Datagram Socket (SOCK_DGRAM) datagram sockets define a non-connected service, and data is transmitted through separate messages, which are unordered and not guaranteed to be reliable and error-free. It uses datagram protocol UDP. (3) The original socket (SOCK_RAW) original socket allows direct access to the underlying protocol such as IP or ICMP, powerful but inconvenient to use, mainly for the development of some protocols.
Socket creation and connection
There are two kinds of byte precedence for computer data storage: high byte precedence and low byte priority. Data on the Internet is transmitted over the network in high order byte precedence, so for machines that store data internally as a low-byte priority, a conversion is required to transfer data over the Internet.
Several byte order conversion functions: Htons ()--"Host to Network short"; HTONL ()--"host to Network Long" Ntohs () – "Network to Host short"; Ntohl ()--"network to Host Long" here, h means "Host", n means "network", s means "short", l means "long".
int socket (int family, int type, int protocol); Family specifies the protocol family; The type parameter specifies the types of sockets: Sock_stream, SOCK_DGRAM, Sock_raw;protocol are usually assigned the value "0".
The socket () call returns an integer socket descriptor that you can use later in the call. Once you return a socket descriptor through the socket call, you should associate the socket with a port on your local computer (often you need to call this function when designing a server-side program.) You can then listen to the service request on that port, and the client typically does not need to call the function.
int bind (int sockfd, struct sockaddr *my_addr, int addrlen); SOCKFD is a socket descriptor , MY_ADDR is a pointer to a SOCKADDR type containing information such as the IP address and port number of the machine; Addrlen are often set to sizeof (struct sockaddr). Finally, one thing to note about the BIND function is that you can use the following assignment to automatically get the native IP address and randomly get a port number that is not occupied: My_addr.sin_port = 0; /* System randomly selects an unused port number */ MY_ADDR.SIN_ADDR.S_ADDR = inaddr_any; /* Fill in the native IP address */ & nbsp; by placing the My_addr.sin_port at 0, the function automatically selects an unoccupied port for you to use. Similarly, by placing my_addr.sin_addr.s_addr as Inaddr_any, the system automatically fills in the native IP address. The bind () function returns 0 when it is successfully invoked, returns "1" when an error is encountered, and resets the errno to the corresponding error number. It is also important to note that when calling a function, the port number is generally not set to a value less than 1024, because 1~1024 is a reserved port number and you can use any port number greater than 1024 that is not occupied.
when binding a socket on a TCP/IP protocol family, we typically use another address structure: struct SOCKADDR_ In { short sin_family; u_short Sin_port; struct in_addr sin_addr; char sin_zero[8]; }; where sin_family af_inet;sin_port indicates the port number; There is only one unique field s_addr in the sin_addr struct that represents the IP address, which is an integer, generally with a function inet_ Addr () converts an IP address in the form of a string into an integer value of unsigned long and then resets to S_ADDR. Some servers are multi-host, there are at least two network cards, then the service program running on such a server can put htonl (inaddr_any) to S_ADDR for its socket, the benefit is that regardless of the network segment of the client program can communicate with the service program If you only bind a fixed IP address to the socket that is running a service program on a multiple host, only the client program that is on the same network segment as the IP address can communicate with the service program. We populate the Sin_zero array with zeros to make the size of the SOCKADDR_IN structure with the SOCThe size of the KADDR structure is consistent. The following is an example of a bind function call: struct sockaddr_in saddr; memset ((void *) &saddr,0,sizeof (SADDR)); saddr.sin_family = af_inet; Saddr.sin_port = htons (8888); saddr.sin_addr.s_addr = htonl (Inaddr_any); //saddr.sin_addr.s_addr = inet_addr ("192.168.22.5"); Bind fixed IP bind (listensocket, (struct sockaddr *) &saddr,sizeof (SADDR)); int Listen (int sockfd, int backlog); SOCKFD is the server-side socket descriptor returned by the socket system call, the backlog specifies the maximum number of requests allowed in the request queue, and incoming connection requests will wait in the queue for accept () them (see below). The backlog limits the number of requests waiting in the queue for services, with most system defaults of 20. When listen encounters an error, the return -1,errno is set to the appropriate error code.
int accept (int sockfd, struct sockaddr *addr, int *addrlen); SOCKFD is the server socket descriptor that is being monitored, addr is usually a pointer to the SOCKADDR_IN variable that holds the client address that made the connection request, and Addrten is usually a pointer to a value of sizeof (struct SOCKADDR_ In) integer pointer variable. An error occurs when a-1 is returned and the corresponding errno value is set. The Accept () function returns a new socket descriptor for use with the new connection, and the data Send () and recv () operations on the new socket descriptor.
Therefore, the server-side program usually in the following order function calls: socket (); Bind (); Listen (); /* Accept () goes here */
The Connect () function is used to establish a TCP connection to the remote server whose function prototype is: int connect (int sockfd, struct sockaddr *serv_addr, int addrlen); SOCKFD is the Sockt descriptor of the destination server; Serv_addr is the address of the server-side IP address and port number. Returns 1 when an error is encountered, and the corresponding error code is included in the errno. Client-side programming does not need to call bind (), because in this case only need to know the destination machine's IP address, and the client through which port to establish a connection with the server does not require concern, the kernel will automatically select an unused End statement client to use.
UDP "Connect": 1, the program can use connect to implement the UDP connection socket, the role is to remember the destination address and destination port in the UDP socket. 2. After using connect, the UDP socket will be discarded if the datagram is not the address and port specified in connect. Without a UDP socket that calls connect, all UDP datagrams arriving at this port will be received without distinguishing between the source port and the address.
About "bind": 1, the client side of the socket does not require bind, the kernel will automatically select an unused port for the client to use, if there are more than one available connection (multiple IP), the kernel will select an IP based on the priority to use as the source IP. 2. If the socket is bound to a specific IP and port using bind, the data will be sent from the specified IP and port, either TCP or UDP.
Socket send and receive data
Send () and recv ()--data transfer for connection-oriented sockets (SOCK_STREAM) for data transfer
int send (int sockfd, const void *msg, int len, int flags); SOCKFD is the socket descriptor that you want to use to transmit data, and MSG is a pointer to the data to be sent. Len is the length of the data in bytes. Flags are typically set to 0 (refer to the man manual for the use of this parameter). The Send () function returns the number of bytes actually sent, possibly less than the data you want to send. Therefore, the return value of Send () needs to be measured. This situation should be handled when the Send () return value does not match Len.
int recv (int sockfd,void *buf,int len,unsigned int flags); SOCKFD is the socket descriptor that accepts data; BUF is the buffer that holds the received data; Len is the length of the buffer. The flags were also set to 0. Recv () returns the number of bytes actually received, or, when an error occurs, returns 1 and resets the corresponding errno value.
Out-of-band data: data transmitted over a channel outside the data flow channel, often used for synchronization and control of remote processes. Only 1 bytes of out-of-band data can be sent at a time in TCP. Send: Send (SOCK_FD, ' f ', 1,msg_oob); Reception: recv (Sock_fd,&out_data,1,msg_oob); Out-of-band data is stored in Out_data.
SendTo () and Recvfrom ()--data transfer for data transfer to a non-connected socket (Sock_dgram/sock_raw)
In the case of a non-connected datagram socket, since the local socket does not establish a connection to the remote machine, the address of the eyesight should be indicated when the data is sent, and the SendTo () function prototype is: int sendto (int sockfd, const void *msg,int le n,unsigned int flags,const struct sockaddr *to,int tolen); The function has two more parameters than the Send () function, to represents the IP address and port number information of the target machine, and Tolen is often assigned to sizeof (struct sockaddr). The SendTo function also returns the length of the data bytes actually sent or returns 1 if a Send error occurs.
int recvfrom (int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); From is a struct sockaddr variable that holds the IP address and port number of the source machine. Fromlen is often used as sizeof (struct sockaddr). When Recvfrom () returns, Fromlen contains the number of bytes of data actually deposited from the from. The Recvfrom () function returns the number of bytes received or returns 1 when an error occurs, collocated with the corresponding errno. It should be noted that when you call the Connect () function for a datagram socket, you can also use Send () and recv () for data transfer, but the socket is still a datagram socket and utilizes the Transport layer's UDP service. However, when the data is sent or received, the kernel automatically adds the target and source address information to it.
Close socket
Close () and shutdown ()--end data transfer when all data operations are finished, you can call the close () function to release the socket, thereby stopping any data manipulation on the socket:
Close (SOCKFD); Close () is an operation on a socket that is closed after the process cannot access the socket. You can also call the shutdown () function to close the socket. This function allows you to stop data transfer in one direction only, while data transfer in one Direction continues. If you can close a socket's write operation and allow the data to continue to be accepted on that socket until all data is read. Shutdown is an operation on a TCP connection.
int shutdown (int sockfd,int how); The meaning of the sockfd is obvious, and the parameter how can be set to the following values: 0-------do not allow to continue to receive data • 1-------do not allow data to continue to be sent • 2-------do not allow the continuation of the sending and receiving of data, are allowed to call Close () Shutd Own returns 0 when the operation succeeds and returns 1 when an error occurs (collocated with the corresponding errno).
IP DNS and other related functions
in_addr_t inet_addr (const char * strptr); Converts the string IP address to the IPV4 address structure in_addr value
char * INET_NTOA (struct in_addr * addrptr); Convert the IPV4 address structure in_addr value to a string IP
Conversion of domain names and IP addresses: struct hostent *gethostbyname (const char *name); The function returns a struct type named Hostent, which is defined as follows: struct hostent { Char *h_name; /* Host's official domain name */ Char **h_aliases; /* A null-terminated array of host aliases */ int h_addrtype; /* Returns the address type in the Internet environment for af-inet */ int h_length; /* Address byte length */ Char **h_addr_list; /* A 0-terminated array containing all addresses of the host */}; #define H_ADDR h_addr_list[0]/* First address in h-addr-list */
Note: The above three functions are non-reentrant, if you write the following code: if (strcmp (Inet_ntoa (IP1), Inet_ntoa (ip2)) = = 0)//Determine whether 2 IP addresses are the same {... The above if condition judgment is always true! When the above three functions are used, the function returns to save the return value immediately, otherwise it will be overwritten by the next call. Because struct in_addr and struct hostent use the static type when they are saved.
Reference: http://www.ibm.com/developerworks/cn/education/linux/l-sock/index.html
Network programming socket Basic API detailed (GO)