socket -- Multiprocess, Multithread Server
Copyright Statement: This article is the original article of the blogger. It can not be reproduced without the permission of the blogger.
First: Concept:
We know that IP addresses are the IP addresses that mark the network without hosts, and port numbers are the addresses that mark different processes on the same host. IP addresses and port numbers mark the unique addresses in the network. (also known as sockets)
In TCP protocol, two processes that build vertical connections have their own sockets to identify, so the two sockets consist of only one socket to identify a connection. The socket book has the meaning of "socket", so it is used to describe the one-to-one correspondence of network connections.
Second: How to solve the problem of large-end and small-end in communication?
We know that the size of each machine may be different. In the network, the same is true. When two hosts communicate, how to solve the problem of the size of the end? Small-end: low-level data at low address, high-level at high address; Big-end: low-level data at high address, high-level at low address. Network data flow first sends low address, then sends out high address. TCP/IP regulations, network data flow. If the receiving host is a small-end sequence and the sending host is a large-end sequence, how to solve the transformation between them?
In order to make the network program portable and make the same C code run normally after compiling on both the big and small computers, the following library functions can be called to convert the network byte order to the host byte order.
If the host is a small-end byte order, these functions convert the corresponding parameters to the left-end byte order and return them to the left-end byte order. If the host is a large-end byte order, these functions do not convert and return the parameters unchanged.
Three: Single-process socket communication
The server:
1: Call socket to request system allocation file descriptor
Parameter type:
The Value of type
2: Call bing to bind local information, including IP address and port number
3: Call listen, listen
Function function: make the file descriptor sockfd returned by the socket into the listening state; backlog: the length of the connection queue, when the number of requests exceeds the length, the error will be reported
4: Call accept to receive socket for connection requests
5:read reads data from socket s
6: Call close to close the socket after communication is completed
Client
1: Call socket to request system allocation file descriptor
2: Call connect to connect to server
3: Call read function standard input to read and read data, put it in custom buffer buf, and then write the data in buf into socket.
4. Call close to close the socket after communication is completed.
Verification:
Makafile file file
.PHONY:all
all:tcp_server tcp_client
tcp:tcp_server tcp_client
gcc- o $@ $^
tcp_client:tcp_client.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f tcp_server tcp_client
tcp_server file:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
int StartUp(int port,const char*ip)
{
int Listen =socket(AF_INET,SOCK_STREAM,0);
if(Listen<0)
{
perror("Listen");
exit(1);
}
struct sockaddr_in local;
local.sin_family =AF_INET;
local.sin_port =htons(port);
local.sin_addr.s_addr =inet_addr(ip);
if(bind(Listen,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("bind");
exit(2);
}
if(listen(Listen,5)<0)
{
perror("listen");
exit(3);
}
return Listen;
}
int main(int argc,const char*argv[])
{
if(argc !=3)
{
printf("input error\n");
return 1;
}
int len;
int Listen =StartUp(atoi(argv[2]),argv[1]);
struct sockaddr_in client;
while(1)
{
int sock = accept(Listen,(struct sockaddr*)&client,&len);
if(sock<0)
{
perror("accept");
continue;
}
printf("get a client ,ip is %s,part is%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
char buf[1024];
while(1)
{
ssize_t s =read(sock,buf,sizeof(buf)-1);//Server Read Data
if(s>0)
{
buf[s] =0;
printf("client #%s\n",buf);
}
else{
//Data read out. Client does not send data
printf("client is quit!\n");
}
}
close(sock);
}
return 0;
}
tcp_client file:
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<arpa/inet.h>
int main(int argc,const char*argv[])
{
int sock =socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket");
return 1;
}
struct sockaddr_in server;
server.sin_family =AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr =inet_addr(argv[1]);
if(connect(sock,(struct sockaddr*)&server,sizeof(server))<0)
{
perror("connect");
return 2;
}
char buf[1024];
while(1)
{
printf("send#");
fflush(stdout);
//Read data from standard input, read to buf, and write from Buf to pipeline
ssize_t s =read(0,buf,sizeof(buf)-1);
if(s<0)
{
perror("read");
return 3;
}
buf[s-1] =0;
write(sock,buf,s);
}
close(sock);
return 0;
}
Result: Server Client:One phenomenon:
What is the reason for this? The server terminates the program. The server is the party initiating the disconnection request. According to TCP's three handshakes and four wave protocols, the party initiating the disconnection request must wait for 2MSL to confirm whether the client receives its own confirmation information. Here, when we run the server immediately, the server is still in the TIME_WAIT state, so the address is occupied when we bind. Solution: After socket, before bind, add statements Int opt = 1; setsockopt (ListenSock, SOL_SOCKET, SO_REUSEADDR, & opt, sizeof (opt)) is to deal with this problem.
Fourth: Multiprocess socket network communication: In practical applications, there may be multiple clients sending data to the server, so the previous single process must have problems, then we need multi-process socket communication, we can achieve: the server can create multiple sub-processes to process the data sent by the client, when each time a new client is received. When we request a connection, we fork() a child process. The parent process is used to wait for the child process, the child process is used to execute, read the data of client method, terminate the child process, and the son process is recycled by its parent process. At this time, the grandchild process is an orphan process, which is processed by process 1.( operating system The goal is not to let the son process wait too long for the grandson process and consume too much system resources.
Note: When the parent process closes the socket and the child process closes the listening socket, the parent process is listening, and no communication child process is reading information and no listening is required. Verification:
Makefile file file
.PHONY:all all:server client server:server.c gcc -o @ ^client:client.c gcc -o @ ^.PHONY: rm -f server client
.server file
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int Startup(int port,const char*ip)
{
int ListenSock =socket(AF_INET,SOCK_STREAM,0);
if(ListenSock<0)
{
perror("socket");
exit(1);
}
int opt =1;
setsockopt(ListenSock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family =AF_INET;
local.sin_port =htons(port);
local.sin_addr.s_addr =inet_addr(ip);
if(bind(ListenSock,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("nind");
exit(2);
}
if(listen(ListenSock,5)<0)
{
perror("listen");
exit(3);
}
return ListenSock;
}
int main(int argc,const char*argv[])
{
if(argc!=3)
{
printf("input error\n");
return 1;
}
int len;
int ListenSocket =Startup(atoi(argv[2]),argv[1]);
struct sockaddr_in client;
while(1)
{
int sock =accept(ListenSocket,(struct sockaddr*)&client,&len);//Get client information
if(sock<0){
perror("accept");
continue;//Acquisition Failure Continuesaccept
}
printf("get a client ,ip is %s,port is %d\n",inet_ntoa(client.sin_addr),\
ntohs(client.sin_port));
int id =fork();
if(id>0)
{
close(sock);
while(waitpid(-1,NULL,WNOHANG)>0);
continue;
}
else{
close(ListenSocket);
if(fork()>0)
{
exit(0);
}
char buf[1024];
while(1)
{
ssize_t s = read(sock,buf,sizeof(buf)-1);
if(s>0)
{
buf[s] =0;
printf("client # %s\n",buf);
}
else{
printf("client is quit\n");
break;
}
}
close(sock);
break;
}
}
return 0;
}
clent file
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<arpa/inet.h>
int main(int argc,const char*argv[])
{
int sock =socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket");
return 1;
}
struct sockaddr_in server;
server.sin_family =AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sock,(struct sockaddr*)&server,sizeof(server)) < 0)
{
perror("connect");
return 2;
}
char buf[1024];
while(1)
{
printf("send# ");
fflush(stdout);
//Read data from standard input, read to buf, and write from buf to pipeline
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
break;
}
buf[s-1] = 0;
write(sock,buf,s);
}
close(sock);
return 0;
}
Of course, this method can also be used as a local loop as the previous one. test But the best way is to connect multiple hosts to send data to server hosts and observe the phenomenon. Fifth, multi-threaded socket network programming: We know that threads are execution branches within the process and run in the address space of the process, while the shortcomings of the process occupy the resources of the system. When users are too many, they can not withstand the access of too many users, so our other side. Method is to use threads to achieve communication. The main thread creates a new thread. The execution function of the new thread is to read information. Similar to the multi-process communication above, we can separate the new thread detch(). After separation, the thread does not need the main thread to wait, but is reclaimed by the operating system area (it is better not to use the join thread to wait, reduced waiting time) to verify. Makefile:. PHONY: all: cli server ENT server: server. C gcc-o @ ^ -lpthread client:client.c gcc -o @ ^ - lpthread.PHONY: rm-f server client.server file
#include<stdio.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
int StartUp(int port,const char* ip)
{
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
perror("socket");
exit(2);
}
int opt = 1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = inet_addr(ip);
if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
{
perror("bind");
exit(3);
}
if(listen(sock,5) < 0)
{
perror("listen");
exit(4);
}
return sock;
}
void* thread_hander(void* arg)
{
int sock = *((int*)arg);
char buf[1024];
while(1)
{
ssize_t _s = read(sock,buf,sizeof(buf)-1);
if(_s > 0)
{
buf[_s-1] = 0;
printf("client say#%s\n",buf);
if(write(sock,buf,sizeof(buf)-1)<0)
{
break;
}
}
else if(_s == 0)
{
printf("client is quit!\n");
break;
}
else
{
perror("read");
break;
}
}
close(sock);
}
int main(int argc,const char* argv[])
{
if(argc != 3)
{
printf("input error\n");
return 1;
}
int listenSock = StartUp(atoi(argv[2]),argv[1]);
struct sockaddr_in client;
int len = 0;
while(1)
{
int sock = accept(listenSock,(struct sockaddr*)&client,&len);
if(sock < 0)
{
perror("accept");
return 5;
}
printf("get a client!ip is %s,port is %d\n",inet_ntoa(client.sin_addr),\
ntohs(client.sin_port));
pthread_t tid;
int ret = pthread_create(&tid,NULL,thread_hander,&sock);
if(ret < 0)
{
perror("pthread_create");
return 6;
}
pthread_detach(tid);
}
return 0;
}
client file
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
int main(int argc, const char* argv[])
{
if(argc != 3)
{
printf("input error\n");
return 1;
}
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
perror("socket");
return 2;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
int ret = connect(sock,(struct sockaddr*)&server,sizeof(server));
if(connect < 0)
{
perror("connect");
return 3;
}
char buf[1024];
while(1)
{
printf("send#");
fflush(stdout);
ssize_t _s = read(0,buf,sizeof(buf)-1);
if(_s > 0)
{
buf[_s - 1] = 0;
if(write(sock,buf,sizeof(buf)-1) < 0)
{
break;
}
ssize_t s = read(sock,buf,sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
printf("server echo#%s\n",buf);
}
}
else
{
perror("read");
return 4;
}
}
return 0;
}
Reference: http://blog.csdn.net/peiyao456/article/details/61934721