processes running on different machines communicate with each other by sending messages to the socket. Each process is like a house, and the socket of the process is a door .
sockets are the door between the application process and TCP , and application developers can control everything on the application layer of the socket, but cannot control the side of the transport layer.
In order to be able to respond to a client program initiating a connection, the server should satisfy:
First, the server program cannot be in hibernation state;
Second, the server program must have some kind of socket.
Socket communication process:
1. The server creates sockets based on address type (IPV4,IPV6), socket type, protocol
2. The server binds the IP address and port number to the socket
3, the server socket listening port number request, ready to receive the connection from the client, this time the server socket is not opened
4. Client creates socket
5, the client opens the socket, according to the server IP address and port number to try to connect to the server socket
6. The server socket receives a client socket request, passively opens, and begins receiving client requests until the client returns the connection information. When the socket enters the blocking state, the so-called blocking is the Accept () method until the client returns the connection information, and begins receiving the next client understanding request
7, the client connection is successful, send the connection status information to the server
8, the server accept method returned, the connection is successful
9. Client writes information to socket
10. The server reads the information
11. Client Shutdown
12, server-side shutdown
1. Create a socket---socket ()
the socket () function is used to assign a descriptor of a socket and the resources it uses according to the specified address family, data type, and protocol.
#include <sys/socket.h>
int socket (int domain, int type, int protocol);
Domain: represents the protocol family to be used by the socket, the protocol family has a detailed definition in "linux/socket.h", the Common protocol family:
<1>:af_unix (native communication)
<2>:af_inet (Tcp/ip-ipv4) DOS, Windows only supports Af_inet
<3>:af_inet6 (Tcp/ip-ipv6)
Type
: Socket type, common type :
<1>:sock_stream (TCP stream: Provides a connection-oriented, reliable data transfer service, data error-free. Sent without duplicates and received in the order in which they were sent. Internal flow control to avoid data flow overrun, data is considered as a byte stream, no length limit, File Transfer Protocol (FTP) using streaming sockets)
<2>:sock_dgram (UDP datagram: provides no connection service.) Datagrams are sent in the form of a separate packet, without error-free assurance that the data may be lost or duplicated and receive confusion. Network File System (NFS) uses datagram sockets)
<3>:sock_raw (RAW socket: This interface allows direct access to lower layer protocols, such as IP, ICMP. Often used to verify new protocol implementations or to access new devices configured in existing services)
protocol: If the caller does not want to specifically specify the protocol to use, the general setting is 0, using the default connection method.
socket is a function, then he also has a return value, when the socket successfully created, return socket, failed to return "1"; error code is written in "ERRNO";
To
create a socket:
#include <sys/type.h>
#include <sys/socket.h>
#include <linux/socket.h>
int soc_fd_tcp;
int soc_fd_udp;
soc_fd_tcp = socket (af_inet, sock_stream,0);
SOC_FD_UDP = socket (af_inet, SOCK_DGRAM, 0);
if (soc_fd_tcp < 0)
{
perror ("TCP SOCKET error\n");
exit ( -1);
}
if (soc_fd_udp < 0)
{
perror ("UDP SOCKET error\n");
exit ( -1);
}
different applications for different sockets, what is the socket in the end?
Answer: Socket socket address! The socket address is a struct, with the TCP transport protocol as an example, the socket address in this data structure contains: Address type, port number, IP address, padding bytes of the 4 data, the prototype is:
#include <netinet/in.h>
struct sockaddr_in
{
unsigned short sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
among them:
sin_family: represents the address type, the value can only be af_inet for communication based on TCP/IP transport protocol;
Sin_port: represents the port number used to identify the local communication process, because each process has its own port number, so you must assign a port number that is not accessed before the communication.
Sin_add: represents a 32-bit IP address;
Sin_zero: represents the padding byte, in general the value is 0;
Assignment of socket data:
struct sockaddr_in sin;//set a sin socket address
sin.sin_family = af_inet;//It is based on the TCP/IP protocol, so the value of sin_family is Af_inet
sin.sin_port = htons;//htons is a port function, which indicates that the port number is
sin.sin_addr.s_addr = inet_addr ("202.96.134.133");//sin_addr is a structural body
memset (sin.sin_zero, 0, sizeof (Sin.sin_zero));//array Sin_zero 0
SIN_ADDR structure prototype:
struct IN_ADDR
{
unsigned long s_addr;
};
2. Specify the local address---the bind () function:
binds a local address to a set of sockets . when a socket () is created, it exists in a namespace (address family), and the Bind () function establishes a local bundle (host address/port number) for the socket by assigning a local name to an unnamed socket.
For example, the corresponding af_inet, Af_inet6 is a IPv4 or IPv6 address and port number combination assigned to the socket.
int bin (int sockfd, const struct SOCKADDR *addr, socklen_t addrlen);
the three parameters of a function are:
SOCKFD: The socket descriptor, which is created by the socket () function and uniquely represents a socket. The bind () function is to bind a name to the description word.
Addr: A const struct sockaddr* pointer to the protocol address to bind to SOCKFD. This address structure differs depending on the address protocol family when the socket is created. such as IPV4:
struct sockaddr_in
{
sa_family_t sin_family;/* Address family:af_inet * /
in_port_t Sin_port; /* port in Network byte order * /
struct IN_ADDR sin_addr; /* Internet address * /
};
/ * Internet address. * /
struct IN_ADDR
{
uint32_t s_addr; /* address in network byte order * /
};
IPv6 corresponds to:
struct SOCKADDR_IN6
{
sa_family_t sin6_family; /* AF_INET6 * /
in_port_t Sin6_port; /* Port number * /
uint32_t sin6_flowinfo;/* IPV6 Flow information * /
struct IN6_ADDR sin6_addr; /* IPV6 address * /
uint32_t sin6_scope_id; * * Scope ID (new in 2.4) */
};
struct IN6_ADDR
{
unsigned char s6_addr[16]; /* IPV6 address * /
};
Addrlen: indicates the corresponding address length.
usually when the server is started, it binds a well-known address (IP address + port number), which is used to provide the service, which the client can use to connect to the server, and the clients do not specify that the system automatically assigns a port number and a combination of its own IP address. This is why the server will call bind () before listen, and the client will not invoke it, but it will be randomly generated by the system at Connect ().
3. Listen and request Connection---listen (), connect () function:
As a server, after calling the socket (), bind () will call listen () to listen to the socket (), as a client, this time should call connect (), make a connection request, the server side will receive this request
int listen (int sockfd, int backlog);
SOCKFD indicates that a locally established, not yet connected socket size, the server receives the request on top of him . The
backlog indicates the maximum length of the request connection queue , which is to tell the socket how many requests to enter when it is busy processing the last request, in other words, this determines the maximum size of the queue that hangs the connection, which is used to limit the number of queued requests. The current maximum allowable value is 5. If no error occurs, listen () returns 0, otherwise, returns: Socket_error.
Listen () can complete the necessary connection for socket SOCKFD of the not-called bind () during the call, and establish a backlog-length request-connection queue.
calling Listen () is the third step in the four steps a server receives for a connection request. It allocates a stream socket in the call socket (), and calls bind () to assign SOCKFD to a name after the call! And to be called before accept ().
int Connect (int sockfd, const struct sockaddr* addr, socklen_t addrlen);
The first parameter is: The client's socket description word;
The second parameter is the address of the server's socket;
The third parameter is the length of the socket address, and the client establishes a TCP connection by invoking the Connect function with the server.
4. Establish socket connection---accept () function:
Accept () is used for connection-oriented servers.
Once the TCP server invokes the socket (), bind (), listen (), it listens to the specified socket () address, and the TCP client calls the socket (), connect () in turn, and sends a connection request to the TCP server. After the TCP server hears this request, it calls the Accept () function to receive the request, so the connection is established, and then the network I/O operation, which is similar to the normal file read/write I/O operation.
int Accept (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Accept function:
The first parameter is the server's socket description word;
The second parameter is a pointer to the struct sockaddr*, which returns the client's protocol address;
The third parameter is the length of the protocol address. If the accept succeeds, then its return value is a completely new description Word generated automatically by the kernel, representing the TCP connection to the returned client.
accept (), Parameters addr and Addrlen store the address information of the client party.
before the call , the parameter addr points to an address structure with an initial value of NULL, while the initial value of Addrlen is 0, and after the call to accept
() , the server waits for a client connection request from a socket numbered sockfd. The connection request is made by the client's connect () call. When a connection request arrives, the Accept () call places the first client socket address and length on the request connection queue into addr and Addrlen, and creates a new socket size that has the same characteristics as SOCKFD. The new socket can be used to process server concurrent requests.
Note:The first parameter of accept is the socket descriptor of the server, which is generated by the server calling the socket () function, which is called: Listener Socket descriptor ; The Accept function returns a connected socket descriptor . A server typically creates only one listener descriptor, which persists throughout the lifetime of the server. The kernel creates a connected socket descriptor for the client connection received by each server process, and when the server completes the service to a customer, the corresponding connection socket descriptor is closed.
5. Data transmission---Send () and recv ()
int Send (int sockfd, const void *buf, size_t 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 typically sends a request to the server with the Send function, and the server usually sends a reply to the client using the Send function.
The Send function:
The first parameter is the specified send end socket description word;
The second parameter is to indicate a buffer where the application will send the data.
The third parameter indicates the number of bytes of data to be sent,
The fourth parameter is generally set to 0;
the execution
flow of the Send function for the socket is described here:
when the Send function is called, send compares the length of the data to besent, Len, and the send buffer length of the socket SOCKFD, which returns SOCKET_ERROR if Len is greater than the SOCKFD send buffer length; If Len is less than or equal to the SOCKFD send buffer length, then send checks the protocol, whether it is sending data for the SOCKFD send buffer, and, if so, waits for the protocol to send the data out. If the protocol has not started sending data for the SOCKFD send buffer or the SOCKFD send buffer has no data, then send compares the remaining space of the SOCKFD send buffer with Len, if Len is greater than the remaining space, Send has been waiting for the protocol to send out the data of the SOCKFD send buffer, and if Len is less than the remaining space, send simply copy the data from the BUF to the remaining space (
Note: Instead of sending the data from the SOCKFD's send buffer to the other end of the connection, the send is simply a copy of the data in the BUF to the remaining space in the SOCKFD send buffer . if the Send function copy data succeeds, it returns the number of bytes actually copied, and if send has an error in copy data, then send returns Sock_error , if the network is disconnected while the send waits for the protocol to transmit the data. Then the Send function also returns SOCKET_ERROR.
Note that the Send function successfully copied the data in the BUF to the remaining space of the SOCKFD's send buffer, but the data is not necessarily immediately passed to the other end of the connection.
If the protocol has a network error during subsequent transfers, the next socket function returns SOCKET_ERROR. (Each of the socket functions except for send will have to wait for the data in the socket's send buffer to continue before execution, and if a network error occurs while waiting, the socket function returns SOCKET_ERROR);
There are three types of return values for the Send function:
(1) return value =0:
(2) return value <0: Send failed, error reason is stored in global variable errno
(3) return value >0: Indicates the number of bytes sent (actually the number of bytes copied into the send buffer)
int recv (int sockfd, void *buf, size_t len, int flags);
Both the client and server side applications use the RECV function to receive data from the other end of the TCP connection.
of the recv function:
The first parameter specifies the receiving end socket description Word;
The second parameter indicates a buffer, which is used to hold the data received by the RECV function;
The third parameter indicates the length of the buf;
The fourth parameter is generally set to 0;
the execution flow of the
recv function of the socket is now described: when the application calls the Recv function, recv waits for the data in the SOCKFD send buffer to be passed by the protocol. If a network error occurs when the protocol re-transmits data in the SOCKFD send buffer, then the RECV function returns SOCKET_ERROR, If there is no data in the data buffer or after the data has been successfully sent by the Protocol, The RECV function checks the receive buffer of the socket SOCKFD first, if there is no data in the SOCKFD receive buffer or the protocol is receiving data, then the recv waits until the protocol receives the data, and when the protocol receives the data, The recv function will copy the data from the SOCKFD receive buffer into the BUF (
Note: The
protocol receives data that may be greater than the length of the buf, so the recv function is called multiple times in this case to copy the data from the receive buffer. The recv function is simply a copy function, and the actual receipt of the data is a protocol to complete.
The RECV function returns the number of bytes of its actual copy. If recv errors in copy, it returns SOCKET_ERROR , and if the recv function waits for the protocol to receive data, the network is interrupted, it returns 0.
The return value type of the RECV function:
(1) When executed successfully, returns the number of bytes received.
(2) If the other end is closed the connection is returned 0, this close is the other side active and normal shutdown
(3) failed to return-1
6. Close the socket---close ()
Close () function: Closes the socket S and releases the resources assigned to the socket, and if s involves an open TCP connection, the connection is freed.
After the server has established a connection with the client, some read and write operations are performed, and the corresponding socket descriptor is closed when the read and write operation is completed, like closing the open file by calling Fclose when the file is opened.
#include <unistd.h>
int close (int fd);
Close the default behavior of a TCP socket by marking the socket as closed and then immediately returning to the calling process. The descriptor can no longer be used by the calling process, that is, no longer as the first parameter of read or write.
Note: The
close operation simply makes the reference count of the corresponding socket descriptor-1, which triggers the TCP client to send a terminating connection request to the server only if the reference count is 0.
Socket principle----SOCKET