Important: The Linux system is programmed via socket sockets for network programming. The network program returns a file descriptor for a communication through the invocation of a socket and several other functions. We can manipulate this descriptor as a descriptor for a normal file, which is the benefit of Linux's device independence. Data communication between networks can be achieved by reading and writing to descriptors.
1. Socket
Function Prototypes:
int socket ( int domain,int type,int protocol);
Parameter explanation:
Domain: Describes the communication protocol family (Af_unix and af_inet, etc.) used by the host on which the network program resides
Af_unix can only be used for single UNIX system interprocess communication, while af_inet can be targeted to the Internet, allowing communication between remote hosts.
Type: Indicates the communication protocol used by the network program (SOCK_STREAM, SOCK_DGRAM, etc.)
Sock_stream indicates the TCP protocol, which provides sequential, reliable, bidirectional, connection-oriented bit streams.
SOCK_DGRAM indicates the UDP protocol, which only provides fixed-length, unreliable, non-connected communication.
Protocol: Because the type is specified earlier, it is OK to assign the value in this general.
The socket provides basic preparation for network communication, returns a file descriptor on success, returns 1 on failure, and can see the details of the error by looking at the errno.
2. Bind
Function Prototypes:
int bind (int sockfd,struct sockaddr *my_addr,int addrlen);
Parameter explanation:
SOCKFD: The file descriptor returned after calling the socket function.
The length of the ADDRLEN:SOCKADDR structure.
MY_ADDR: Pointer to sockaddr.
Where the structure of SOCKADDR is defined as:
struct sockaddr{ short sa_family; Char sa_data[];};
However, due to the compatibility of the system, we generally do not use this header file, and another structure (struct sockaddr_in) instead. There is a definition of sockaddr_in in:
struct sockaddr_in{ short sin_family; Short int Sin_port; struct in_addr sin_addr; Char sin_zero[8];};
Sin_family is generally af_inet,
The sin_addr set to Inaddr_any indicates that it can communicate with any host.
Sin_port is the port number we want to listen to. Sin_zero[8] is used to populate.
Bind binds the local port with the file descriptor returned by the socket, returns 0 on success, and 1 on failure.
3, listen
Function Prototypes:
int Listen (int sockfd,int backlog);
Parameter explanation:
SOCKFD: Is the file descriptor after bind.
Backlog: Sets the maximum length of the request queue. Use this to indicate the length of the queue that can be described when multiple client programs and server connections are connected.
The Listen function changes the file descriptor of bind to a listener socket, returns 0 on success, and 1 on failure.
4. Accept
Function Prototypes:
int Accept (int sockfd,struct sockaddr *addr,int *addrlen);
Sockfd:listen the listener socket.
Addr and Addrlen are used to fill the client's program, the server side as long as the pointer can be passed.
Bind, listen, and accept are functions used on the server side. When the accept call is made, the server-side program blocks until a client program makes a connection. When accept succeeds, it returns the last server-side file descriptor, at which point the server can write information to the descriptor. Returns-1 on failure.
5. Connect
Function Prototypes:
int Connect (int sockfd,struct sockaddr *serv_addr,int addrlen);
The file descriptor returned by the Sockfd:socket.
SERV_ADDR: Stores the server-side connection information, where SIN_ADDR is the address of the service side.
The length of the addrlen:serv_addr.
The Connect function is the client used to connect to the server, returns 0 on success, and 1 on failure. SOCKFD is a file descriptor that communicates with the server.
Instance one server program
#include <stdlib.h>#include<stdio.h>#include<errno.h>#include<string.h>#include<unistd.h>#include<netdb.h>#include<sys/socket.h>#include<netinet/inch.h>#include<sys/types.h>#include<arpa/inet.h>intMainintargcChar*argv[]) { intSOCKFD, NEW_FD; structsockaddr_in server_addr; structsockaddr_in client_addr; intSin_size, PortNumber; CharHello[] ="helloworld\n"; if(ARGC! =2) {fprintf (stderr,"usage:%s portnumber\a\n", argv[0]); Exit (1); } if(PortNumber = atoi (argv[1])) <0) {fprintf (stderr,"usage:%s portnumber\a\n", Strerror (errno)); Exit (1); } //The server begins to build the socket descriptor if(SOCKFD = socket (af_inet, Sock_stream,0)) == -1) {fprintf (stderr,"Socket error:%s\n\a", Strerror (errno)); Exit (1); } //server-side fill SOCKADDR structureBzero (&SERVER_ADDR,sizeof(structsockaddr_in)); Server_addr.sin_family=af_inet; Server_addr.sin_addr.s_addr=htonl (Inaddr_any); Server_addr.sin_port=htons (portnumber); //binding SOCKFD Descriptors if(Bind (SOCKFD, (structsockaddr*) (&SERVER_ADDR),sizeof(structSOCKADDR)) = =-1) {fprintf (stderr,"Bind error:%s\n\a", Strerror (errno)); Exit (1); } //Monitoring SOCKFD descriptors if(Listen (SOCKFD,5) == -1) {fprintf (stderr,"Listen error:%s\n\a", Strerror (errno)); Exit (1); } while(1) { //the server blocks until the client program establishes a connectionSin_size =sizeof(structsockaddr_in); if(new_fd = Accept (SOCKFD, (structsockaddr*) (&CLIENT_ADDR), &sin_size)) = =-1) {fprintf (stderr,"Accept error:%s\n\a", Strerror (errno)); Exit (1); } fprintf (stderr,"Server get connection from%s\n", Inet_ntoa (CLIENT_ADDR.SIN_ADDR)); if(Write (new_fd, hello, strlen (hello)) = =-1) {fprintf (stderr,"Write error:%s\n\a", Strerror (errno)); Exit (1); } close (SOCKFD); Exit (0); }}
Client programs
#include <stdlib.h>#include<stdio.h>#include<errno.h>#include<string.h>#include<unistd.h>#include<netdb.h>#include<sys/socket.h>#include<netinet/inch.h>#include<sys/types.h>#include<arpa/inet.h>intMainintargcChar*argv[]) { intSOCKFD; Charbuffer[1024x768]; structsockaddr_in server_addr; structHostent *host; intportnumber,nbytes; if(argc!=3) {fprintf (stderr,"usage:%s hostname portnumber\a\n", argv[0]); Exit (1); } if((Host=gethostbyname (argv[1]))==NULL) {fprintf (stderr,"gethostname error\n"); Exit (1); } if((Portnumber=atoi (argv[2])) <0) {fprintf (stderr,"usage:%s hostname portnumber\a\n", argv[0]); Exit (1); } /*client program starts to build SOCKFD descriptor*/ if(Sockfd=socket (Af_inet,sock_stream,0))==-1) {fprintf (stderr,"Socket error:%s\a\n", Strerror (errno)); Exit (1); } /*client program fills the data on the service side*/bzero (&SERVER_ADDR,sizeof(SERVER_ADDR)); Server_addr.sin_family=af_inet; Server_addr.sin_port=htons (portnumber); Server_addr.sin_addr=*((structIN_ADDR *) host->h_addr); /*client program initiates connection request*/ if(Connect (SOCKFD,structSOCKADDR *) (&SERVER_ADDR),sizeof(structSOCKADDR)) ==-1) {fprintf (stderr,"Connect error:%s\a\n", Strerror (errno)); Exit (1); } /*the connection was successful.*/ if(Nbytes=read (Sockfd,buffer,1024x768))==-1) {fprintf (stderr,"Read error:%s\n", Strerror (errno)); Exit (1); } Buffer[nbytes]=' /'; printf ("I have received:%s\n", buffer); /*End Communication*/Close (SOCKFD); Exit (0);}
Simple summary:
Server-Side build process: socket-->bind-->listen-->accept
Client: Socket-->connect
Introduction of Elementary Network function