TCP网络编程——并发执行

在TCP网络编程中,当服务器使用单一进程处理客户端连接时,会因recv()阻塞而无法接受新的连接。为实现并发处理,本文探讨了通过创建多线程和多进程的方法。在多线程方案中,服务器接收到客户端连接后创建新线程处理数据;而在多进程方案中,父进程fork()后,子进程处理客户端连接,完成后关闭连接。这两种方法能有效提升服务器处理并发连接的能力。
摘要由CSDN通过智能技术生成

目录

用多线程处理

用多进程处理


对于之前博客中的代码。当一个客户端和服务器建立连接以后,服务端accept()返回,然后准备循环接收客户端发送的数据。如果客户端暂时没有发送数据,服务端绘制recv()处阻塞住。此时如果其他客户端向服务端发起连接,就无法进行accept()。也就是说,服务器无法同时处理多个客户端。

为了解决这个问题,我们可以引入多线程和多进程。

服务器接收一个客户端的连接后,创建一个线程或者进程,然后在新创建的线程或进程中循环处理数据。主线程只负责监听客户端连接,使用accept()接收连接。

用多线程处理

思路:完成三次握手后,客户端进入线程,再连接服务器端,就可以实现并发;

或者在while()循环中使用线程进行accept()

服务端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pt
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
popen重写 /* * ===================================================================================== * * Filename: tcpserver.c * * Description: this program is demostrate to how to write a remote control server * * Version: 1.0 * Created: 2010年09月11日 21时28分21秒 * Revision: none * Compiler: gcc * * Author: Gang Liang (cs.scu.edu.cn/~lianggang), lianggang@scu.edu.cn * Company: Sichuan university * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #define PORT 8900 #define BUFSIZE 2048 #define SHELL "/bin/sh" FILE *myPopen(char *command,char *type) { int f_des[2]; int pid_t; // pipe(f_des); if((type[0]!='r'&&type[0]!='w')||type[1]!=0) { printf("myPopen()flag error/n"); return NULL; } if(pipe(f_des)==-1) { printf("pipe create error/n"); return NULL; } pid_t=fork(); if(pid_t<0) return NULL; if(pid_t==0) { if(type[0]=='r') { close(f_des[0]); dup2(f_des[1],STDOUT_FILENO); close(f_des[1]); } else{ close(f_des[1]); dup2(f_des[0],STDIN_FILENO); close(f_des[0]); } execl(SHELL,"sh","-c",command,(char*)0); _exit(127); char *argv[] = {command,0}; if(execvp(command,argv)==-1) return NULL; } wait(0); if(type[0]=='r') { close(f_des[1]); return fdopen(f_des[0],"r"); } else{ close(f_des[0]); return fdopen(f_des[1],"w"); } } int execute(char*command,char*buf) { FILE *fp; int count; char commandbuf[2056]; if ((NULL==command)||(NULL==buf)) { perror("command or buf is empty\n"); return -1; } count =0; memset(commandbuf,0,2056); strcat(commandbuf,"sh -c "); strcat(commandbuf,command); fprintf(stderr,"the command is %s\n",commandbuf); if (NULL==(fp=myPopen(commandbuf,"r"))) { perror("create pipe error\n"); return -1; } while ((count<2047) && (EOF!=(buf[count++]=fgetc(fp)))); buf[count-1]='\0'; return count; } int main() { int sockfd; int conn_sock; char sendbuf[BUFSIZE]; char recvbuf[BUFSIZE]; int sendnum; int recvnum; int length; struct sockaddr_in client; struct sockaddr_in server; int opt; int cnt; pid_t pid; /* The first stage:INITILIZE */ memset(&client,0,sizeof(client)); memset(&server,0,sizeof(server)); memset(sendbuf,0,BUFSIZE); memset(recvbuf,0,BUFSIZE); length=0; sockfd=-1; conn_sock=-1; opt=SO_REUSEADDR; /*The second stage:create listen socket */ if (-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))) { perror("create socket error\n"); return -1; } setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); /* The third stage:bind socket */ server.sin_family=AF_INET; server.sin_addr.s_addr=htonl(INADDR_ANY); server.sin_port=htons(PORT); if (-1==bind(sockfd,(struct sockaddr*)&server,sizeof(server))) { perror("bind socket error\n"); close(sockfd); return -1; } /* The fourth stage:listen socket */ if (-1==listen(sockfd,10)) { perror("listen socket error\n"); close(sockfd); return -1; } /* The fifth stage:creat connect socket */ while(1) { if (-1==(conn_sock=accept(sockfd,(struct sockaddr*)&client,&length))) { perror("three shakehands error\n"); close(sockfd); return -1; } /* the commnication with client */ pid=fork(); if(pid==0) { close(sockfd); while(1) { memset(recvbuf,0,BUFSIZE); memset(sendbuf,0,BUFSIZE); if (0>=(recvnum=read(conn_sock,recvbuf,BUFSIZE))) { perror("the commucation error\n"); close(conn_sock); close(sockfd); return -1; } recvbuf[recvnum]='\0'; fprintf(stderr,"the command is:%s\n",recvbuf); if (0==strcmp(recvbuf,"quit")) { fprintf(stderr,"the client is quit\n"); close(conn_sock); break; } if (1>=(cnt=execute(recvbuf,sendbuf))) { sprintf(sendbuf,"the invalid command,please try again\n"); } fprintf(stderr,"the result is \n%s",sendbuf); if (0>=(sendnum=write(conn_sock,sendbuf,strlen(sendbuf)))) { perror("the commucation error\n"); close(sockfd); close(conn_sock); return -1; } } } else if(pid>0) { close(conn_sock); continue; } } close(sockfd); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值