目标:
完成一个精简TCP服务器,可接收来自多个用户的请求,并返回结果。
思路:
(1)服务器
C++ TCP服务器的实现主要由以下几个函数来完成:
a)socket
创建服务器监听套接字
b)bind
绑定服务器监听信息到套接字上
c)listen
开始监听,接收客户端的TCP连接
d)accept
从listen所维护的队列中取出一条已连接的TCP,返回该连接的socket描述字
e)服务器客户端在连接socket描述字上进行消息通信
f) close
关闭打开着的套接字
为了更好的服务多个发起请求的客户端,在e步骤上,我们使用fork以派生子进程来独立处理每个客户端的请求。
if( (childpid=fork())==0)
{
close(listenfd); //从父进程复制下来的监听socket描述符要关闭。
//communication(connfd);
exit(0);
}
(2)客户端
客户端的实现主要由以下函数完成:
a)socket
创建客户端连接套接字
b)connect
向指定服务器发起连接请求
c)服务器客户端在连接socket描述字上进行消息通信
d)close
关闭打开着的套接字
实现:
server.cpp
1 #include<sys/types.h> 2 #include<sys/socket.h> 3 #include<strings.h> 4 #include<arpa/inet.h> 5 #include<unistd.h> 6 #include<stdlib.h> 7 #include<stdio.h> 8 #include<string.h> 9 #include<errno.h>10 #include<signal.h>11 #include<sys/wait.h>12 13 #define LISTEN_PORT 8414 void str_echo(int sockfd)15 {16 ssize_t n;17 char line[512];18 19 printf("ready to readn");20 while( (n=read(sockfd,line,512))>0 )21 {22 line[n]=' ';23 printf("Client: %sn",line);24 bzero(&line,sizeof(line));25 }26 printf("end readn");27 }28 29 int main(int argc, char **argv)30 {31 int listenfd, connfd;32 pid_t childpid;33 socklen_t chilen;34 35 struct sockaddr_in chiaddr,servaddr;36 37 listenfd=socket(AF_INET,SOCK_STREAM,0);38 if(listenfd==-1)39 {40 printf("socket established error: %sn",(char*)strerror(errno)); return -1;41 }42 43 bzero(&servaddr,sizeof(servaddr));44 servaddr.sin_family=AF_INET;45 servaddr.sin_addr.s_addr=htonl(INADDR_ANY);46 servaddr.sin_port=htons(LISTEN_PORT);47 48 int bindc=bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));49 if(bindc==-1)50 {51 printf("bind error: %sn",strerror(errno)); return -1;52 }53 54 listen(listenfd,5);55 for(;;)56 {57 chilen=sizeof(chiaddr);58 59 connfd=accept(listenfd,(struct sockaddr*)&chiaddr,&chilen);60 if(connfd==-1)61 { printf("accept client error: %sn",strerror(errno)); return -1; }62 else 63 printf("client connectedn");64 65 if((childpid=fork())==0)66 {67 close(listenfd);68 printf("client from %sn",inet_ntoa(chiaddr.sin_addr));69 str_echo(connfd);70 exit(0); 71 }72 else if (childpid<0)73 printf("fork error: %sn",strerror(errno));74 close(connfd);75 }76 }
client.cpp
1 #include<sys/types.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include<unistd.h> 5 #include<sys/socket.h> 6 #include<strings.h> 7 #include<string.h> 8 #include<arpa/inet.h> 9 #include<errno.h>10 11 #define SERVER_PORT 8412 void str_cli(char *data,int sockfd)13 {14 char recv[512];15 16 int wc=write(sockfd,data,strlen(data));17 18 exit(0);19 }20 int main(int argc, char **argv)21 {22 int sockfd;23 struct sockaddr_in servaddr;24 25 if(argc!=3)26 return -1;27 28 sockfd=socket(AF_INET,SOCK_STREAM,0);29 if(sockfd==-1)30 {31 printf("socket established error: %sn",(char*)strerror(errno)); return -1;32 }33 34 bzero(&servaddr,sizeof(servaddr));35 servaddr.sin_family=AF_INET;36 servaddr.sin_port=htons(SERVER_PORT);37 inet_pton(AF_INET,argv[1],&servaddr.sin_addr);38 39 printf("client try to connectn");40 int conRes=connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));41 if(conRes==-1)42 { 43 printf("connect error: %sn",strerror(errno)); return -1;44 }45 46 str_cli(argv[2],sockfd);47 48 exit(0);49 }
分析:
最简单的服务器仅能完成基本的通信,并没有考虑其他边界或者异常情况,同时,采用子进程处理客户端连接,一旦子进程数量增多,并且子进程需要长时间的运行,那么服务器性能将严重下降。
原文链接: https://www.cnblogs.com/aga-j/archive/2011/09/15/2177018.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/32352
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!