当前位置:网站首页>Implement a server with multi process concurrency
Implement a server with multi process concurrency
2022-07-02 14:37:00 【Kallou】
Project source : Sign in — major IT Written interview preparation platform _ Cattle from
This course teaches how to use socket API Implement a TCP Multi process concurrent server of the Protocol . Before implementing the server , First of all, let's get to know TCP The process of communication and the various API.
1.TCP Communication process
TCP In communication , The end that initiates the connection request is called the client , The end that passively accepts the connection is called the server .
Server side :
1. establish A monitor Socket
- monitor : Listen for client connections
- Socket : One socket File descriptor ……socket()
2. Put the File descriptor And local IP And port binding ( Binding socket Address information )……bind()
- This is what the client uses when connecting to the server IP And port
3. Set listening , Listen for the file descriptor to start working ( client socket File to server socket The read buffer of the file sends data , Server side socket Is to monitor whether there is data in your read buffer , The process is carried out by OS complete )……listen()
- Monitoring itself does not accept requests , If you find a connection in the buffer, you will go to the next step
4. Block waiting , until Client initiates connection , After receiving the client connection, a Another one is used to communicate with clients socket……accept()
5. signal communication .……Window:recv()/send() Linux:read()/write()
6. End of communication , close Connect .……close()
Why launch another after listening to the request socket For communicating with clients ?
Suppose that there are two clients that successively initiate a connection and use the same socket Accept connections and communicate , After accepting the first client connection socket Start communicating , At this time, the second client also sent a request ,socket If you accept the request here, you have to communicate with two clients at the same time , and socket Only the address information of one client can be recorded in the file , Isn't that a mess . Therefore, you must accept the connected socket And... For communication socket Distinguish , Use one socket Specifically accept connections , You can create as many connections as you want socket Communicate with .
It also shows TCP Connection oriented features , That is, communication can only be one-to-one , One socket Corresponding to one socket.
client :
1. establish A for communication Socket .( Port number from os Automatically assigned )……socket()
2. Connect to server , It is necessary to formulate the destination server IP And port ……connect()
3. Successful connection , communicate ……send()
4. End of communication , disconnect ……close()
2.socket API
all socket API Need to import header file #include<arpa/inet.h>
- socket()
int socket(int domain, int type, int protocol);
Parameters :
-domain: Specify the address protocol family .
Common values :AF_INET(IPv4),AF_INET6(IPv6)
-type: The type of protocol used in communication .
Common values :SOCK_STREAM( Streaming Protocol ),SOCK_DGRAM( Declarative agreement )
-protocol: Specific protocols used .
General writing 0,os It will be automatically derived according to the first two values .
Return value :
success : Returns the socket file descriptor
Failure :-1
Here, the return file descriptor explains again socket The essence of is document . So just create socket, You can use its returned file descriptor in other functions , Operate like a file socket 了 . In fact, other functions do this .
- bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Parameters :
-sockfd: jointed socket File descriptor .
-addr: Server process socket Information
Here formal parameters are used struct sockaddr* type , The actual arguments passed in are generally not of this type , Type conversion required
-addrlen:addr The length of
Return value :
Failure :-1
- listen()
int listen(int sockfd, int backlog);
Parameters :
-sockfd: ditto
-backlog: Request queue length
A server process may receive multiple client requests , Before the last request is completed, the new request will be put into the buffer of a queue structure , This buffer is called the request queue .
Return value :
Failure :-1
- accept()
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Parameters :
-sockfd: ditto
-addr: Used to return to the client socket Address information
-addrlen:addr The length of
Return value :
success : Back to a new socket File descriptor , This file descriptor is used with addr The indicated client communicates
Failure :-1
- connect()
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Parameters : Same as bind()
Return value :
success :0
Failure :-1
- write()、read()
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
Parameters :
-fd: communicational socket File descriptor
-buf: To write / Reading data .write Write data to the write buffer ,read Get data from the read buffer
-count:buf length
3. Code example of multiple concurrent servers
This sample program demonstrates an echo client , That is, the client enters a piece of data , The server returns the same data .
Every time the server accepts a connection , Just print the connected client ip And port number .
Multiple clients can access at the same time , The server will create multiple sub processes to request new for each client socket Maintain communication .
Server side :server_process.c
//TCP Communication multiple concurrent server
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
// establish socket
int lfd = socket(AF_INET,SOCK_STREAM,0);
if(lfd == -1){
perror("socket");
exit(-1);
}
// binding
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(9999);
saddr.sin_addr.s_addr = INADDR_ANY;
int ret = bind(lfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret == -1){
perror("bind");
exit(-1);
}
// monitor
ret = listen(lfd,128);
if(ret == -1){
perror("listen");
exit(-1);
}
// Loop waiting for client connection
while(1){
struct sockaddr_in cliaddr;
int len = sizeof(cliaddr);
// Accept the connection
int cfd = accept(lfd,(struct sockaddr*)&cliaddr,&len);
if(cfd == -1){
perror("accept");
exit(-1);
}
// Enter every connection , Then create a sub process to communicate with the client
pid_t pid = fork();
if(pid == 0){
// Subprocess created successfully
// Get client information
char cliIP[16];
inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,cliIP,sizeof(cliIP));
unsigned short cliPort = ntohs(cliaddr.sin_port);
printf("client ip is : %s,port is %d\n",cliIP,cliPort);
// Receive data from client
char recvBuf[1024] = {0};
while(1){
int len = read(cfd,&recvBuf,sizeof(recvBuf));
if(len == -1){
perror("read");
exit(-1);
}else if(len > 0){
printf("recv client data : %s\n",recvBuf);
}else{
printf("client closed...");
}
/*
The third parameter +1 Is to bring the newline character in the returned character ,
Otherwise, if the length of the string sent twice is different , May return to
Last left character
*/
write(cfd,recvBuf,strlen(recvBuf)+1);
}
close(cfd);
exit(0);
}
}
close(lfd);
return 0;
}
client :client.c
// TCP Communication client
#include<stdio.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
//1. Create socket
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd == -1)
{
perror("socket");
exit(-1);
}
//2. Connect to the server side
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
inet_pton(AF_INET,"192.168.59.129",&serveraddr.sin_addr.s_addr);
serveraddr.sin_port=htons(9999);
int ret = connect(fd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(ret == -1)
{
perror("connect");
exit(-1);
}
//3. signal communication
int mnum = 10;
char recvBuf[1024] = {0};
while(mnum > 0)
{
// The client sends data to the server
char * data;
printf("Input:");
scanf("%s",data);
write(fd,data,strlen(data)+1);// Same as the server write The function is the same , Here to +1 Pass newline
//sleep(1);
// Read the data sent by the server
int len = read(fd,recvBuf,sizeof(recvBuf));
if(len == -1)
{
perror("read");
exit(-1);
}else if(len > 0){// Indicates that data has been obtained ,len Is the length of the acquired data
printf("recv server data: %s\n",recvBuf);
mnum--;
}else if(len == 0){// Indicates that the server is disconnected
printf("server closed...\n");
break;
}
}
//4. Close the connection
close(fd);
return 0;
}
边栏推荐
- 跨服务器数据访问的创建链接服务器方法
- The use of TestNG, the testing framework (II): the use of TestNG XML
- fatal: unsafe repository is owned by someone else 的解决方法
- Data Lake (11): Iceberg table data organization and query
- STM32 standard firmware library function name memory (II)
- php链表创建和遍历
- Fabric.js 元素被选中时保持原有层级
- Fabric. JS dynamically set font size
- STM32 library function for GPIO initialization
- Fabric.js 自由绘制圆形
猜你喜欢
PyQt5_ Qscrollarea content is saved as a picture
obsidian安装第三方插件——无法加载插件
YoloV6训练:训练自己数据集遇到的各种问题
每日学习3
途家木鸟美团夏日折扣对垒,门槛低就一定香吗?
Makefile separates file names and suffixes
Design and implementation of car query system based on php+mysql
微信小程序使用towxml显示公式
关于Flink框架窗口(window)函数最全解析
Yolov6 training: various problems encountered in training your dataset
随机推荐
【apipost】使用教程
关于Flink框架窗口(window)函数最全解析
Design and implementation of car query system based on php+mysql
Stm32-dac Experiment & high frequency DAC output test
fatal: unsafe repository is owned by someone else 的解决方法
Makefile 分隔文件名与后缀
字符串匹配问题
大顶堆、小顶堆与堆排序
Yolov6 training: various problems encountered in training your dataset
[to be continued] [UE4 notes] l5ue4 model import
Method of creating linked server for cross server data access
STM32标准固件库函数名(一)
篇9:XShell免费版安装
Thoroughly master prototype__ proto__、 Relationship before constructor (JS prototype, prototype chain)
Some interview suggestions for Android programmers "suggestions collection"
Fabric. JS free drawing ellipse
跨服务器数据访问的创建链接服务器方法
Fabric. JS manual bold text iText
Essential elements of science fiction 3D scenes - City
由粒子加速器产生的反中子形成的白洞