I. Introduction to the Concept
Network programs are divided into server-side programs and client programs. The service side is the one that provides the service, and the client is the party requesting the service. But the reality is that some programs of the client, server-side role is not so obvious, that is, mutual client and service side.
When we write a network program, it is generally based on TCP protocol or UDP protocol for network communication.
TCP: (Transfer control Protocol) transmission protocol is a connection-oriented protocol, and when our network program uses this protocol, the network can ensure that the transmission between our client and server is reliable.
UDP: (User Datagram Protocol) Subscriber Datagram Protocol is a non-connection-oriented protocol that does not guarantee the reliability of the connection of our network programs.
The type of protocol that we write about the network program depends on the specific circumstances. For example, if a large amount of data traffic, and the integrity of the data requirements are not particularly high, you can use the UDP protocol to get faster transmission rate. If we are to implement some functions, such as file transfer, social communication, we need to use TCP protocol communication to ensure the reliability of transmission.
Two. Introduction to Elementary Network functions
NT socket (int domain, int type,int protocol)
Domain: Describes the host of our network program used by the Communication Association (AF_UNIX and Af_inet, etc.).
Af_unix can only be used for single UNIX system interprocess communication,
And Af_inet is for the internet, so it allows you to allow remote
Communication between hosts (when we find that the domain option is pf_* instead of af_* when we're a man socket, because GLIBC is a POSIX implementation, it replaces AF with PF,
But we can all use it.
Type: The communication protocol (SOCK_STREAM,SOCK_DGRAM, etc.) that our network program uses
Sock_stream shows that we are using the TCP protocol, which provides sequential, reliable, bidirectional, and connection-oriented bit streams.
Sock_dgram shows that we are using the UDP protocol, which will only provide fixed-length, unreliable, connectionless communications.
Protocol: Because we specified the type, so this place we generally as long as the 0来 instead of the socket for network communication to do basic preparation.
Returns a file descriptor on success, returns 1 when it fails, and looks at the details of the error that errno can see.
int bind (int sockfd, struct sockaddr *my_addr, int addrlen)
SOCKFD: Is the file descriptor returned by the socket call.
Addrlen: Is the length of the SOCKADDR structure.
MY_ADDR: is a pointer to a sockaddr. There is a definition of sockaddr in the
struct sockaddr{
unisgned short as_family;
Char sa_data[14];
};
However, due to the compatibility of the system, we generally do not use this header file, instead of using another structure (struct sockaddr_in) to replace. There are sockaddr_in definitions in
struct sockaddr_in{
unsigned short sin_family;
unsigned short int sin_port;
struct IN_ADDR sin_addr;
unsigned char sin_zero[8];
}
We mainly use the internet so
Sin_family is generally af_inet,
Sin_addr set to Inaddr_any indicates that it can communicate with any host.
Sin_port is the port number that we are listening to. Sin_zero[8] is used to populate.
Bind binds the local port to the file descriptor returned by the socket. Success is to return 0, the failure is the same as the socket
int listen (int sockfd,int backlog)
SOCKFD: Is the file descriptor after bind.
Backlog: Sets the maximum length of the request queue. Use this representation to describe the queue length when there are multiple client programs connected to the server.
The Listen function changes the file descriptor for bind to a listening socket. The situation returned is the same as bind.
int accept (int sockfd, struct sockaddr *addr,int *addrlen)
SOCKFD: Is the listen file descriptor.
Addr,addrlen is used to fill in the client's program, server-side as long as passing the pointer on it. Bind,listen and accept are server-side functions,
When accept calls, the server-side program blocks until a client program sends a connection. Returns the last server-side file descriptor when accept succeeds,
This time the server side can write information to the descriptor. Return at failure-1
int connect (int sockfd, struct sockaddr * serv_addr,int addrlen)
Sockfd:socket returns the file descriptor.
SERV_ADDR: Server-side connection information is stored. Where Sin_add is the address of the service side
Length of Addrlen:serv_addr
The Connect function is used by the client to connect to the server end. Return 0,SOCKFD on success returns-1 when the file descriptor that communicates with the server fails.
More functions See man ....
int getaddrinfo (const char *node, const char *service,
const struct Addrinfo *hints,
struct addrinfo **res);
Three. Application of elementary Network function
A textbook server-side program process is:
Establish socket socket ()---> Bind socket to IP address bind ()-----> Establish listening Socket listen ()------> Start waiting for client request Accpet ()
The detailed code is as follows:
The code is as follows:
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main (int argc, char *argv[])
{
int SOCKFD,CONNFD;
struct sockaddr_in srvaddr;
struct sockaddr_in cliaddr;
int len,port;
Char hello[]= "hi,welcome to Linux-code!n";
if ((Sockfd=socket (af_inet,sock_stream,0)) ==-1) {
fprintf (stderr, "Socket Error:%sna", Strerror (errno));
Exit (1);
}
/* Server-side FILLED SOCKADDR structure * *
Bzero (&srvaddr,sizeof (struct sockaddr_in));
Srvaddr.sin_family=af_inet;
Srvaddr.sin_addr.s_addr=htonl (Inaddr_any);
Srvaddr.sin_port=htons (1113);
/* Bundle SOCKFD Descriptor * *
if (Bind (SOCKFD, (struct sockaddr *) (&SRVADDR), sizeof (struct sockaddr)) ==-1) {
fprintf (stderr, "Bind Error:%sna", Strerror (errno));
Exit (1);
}
/* Monitor SOCKFD Descriptor * *
if (Listen (sockfd,5) ==-1) {
fprintf (stderr, "Listen Error:%sna", Strerror (errno));
Exit (1);
}
len=sizeof (struct sockaddr_in);
while (1) {/* The server is blocked until the client program establishes the connection * *
if ((Connfd=accept (SOCKFD, (struct sockaddr *) (&CLIADDR), &len)) ==-1) {
fprintf (stderr, "Accept Error:%sna", Strerror (errno));
Exit (1);
}
fprintf (stderr, "Server get connection from%sn", Inet_ntoa (CLIADDR.SIN_ADDR));
if (Write (Connfd,hello,strlen (hello)) ==-1) {
fprintf (stderr, "Write error:%sn", Strerror (errno));
Exit (1);
}
* * This communication is over/
Close (CONNFD);
/* Loop the next one * *
}
Close (SOCKFD);
Exit (0);
}
A textbook client-side program process is:
Establish socket socket ()---> Connect to the Server ()
The detailed code is as follows:
The code is as follows:
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main (int argc, char *argv[]) {
int sockfd; Char buf[1024];
struct sockaddr_in srvaddr;
struct Hostent *phost; int nbytes;
if (argc!=3) {
fprintf (stderr, "usage:%s an ", argv[0]);
Exit (1);
}
/* Client program started to establish SOCKFD descriptor */
if ((Sockfd=socket (af_inet,sock_stream,0)) ==-1) {
fprintf (stderr, "Socket Error:%san", strerror (errno));
Exit (1);
}
/* Customer program to populate the service side of the information * *
Bzero (&srvaddr,sizeof (SRVADDR));
Srvaddr.sin_family=af_inet;
Srvaddr.sin_port=htons (Atoi (argv[2));
if (Inet_pton (Af_inet, argv[1], &srvaddr.sin_addr) <= 0) {
fprintf (stderr, "Inet_pton Error:%san", Strerror (errno));
Exit (1);
}
/* Client initiated connection request/*
If Connect (sockfd, (struct sockaddr *) (&SRVADDR), sizeof (struct sockaddr)) ==-1) {
fprintf (stderr, "Connect Error:%san", Strerror (errno));
Exit (1);
}
/* The connection was successful * *
if ((Nbytes=read (sockfd,buf,1024)) ==-1) {
fprintf (stderr, "read Error:%sn", Strerror (errno));
Exit (1);
}
Buf[nbytes]= ';
printf ("Received DATA:%SN", buf);
/* End of Communication *
Close (SOCKFD);
Exit (0);
}
Four. Problems with the above procedures
Run the server-side program of the above program before running the client program, and you can get the following results:
Server-side results:
Viidiot@ubuntu:~/code $./srv
Server get connection from 192.168.1.153
Server get connection from 127.0.0.1
Server get connection from 192.168.1.153
Client End Results:
Viidiot@ubuntu:~/code $./CLI 192.168.1.153 1113
Received Data:hi,welcome to linux-code!
We have completed a Simple network communication program, which uses an IO model for synchronous (synchronous) blocking (blocking). Server-side call accept (), write () and other functions, if there is no client connection or the corresponding file descriptor is not ready to write, the program will be there to wait, nothing to do. In practical applications, such programs are rarely present. The asynchronous IO model is used in practice.
Let's take a look at it again: synchronous, asynchronous, blocking, non-blocking, select ()/poll ()/epoll ()