简单的并发服务器(C/S端)

2 篇文章 0 订阅

服务器端采用简单的socket编程制作,多个客户端同时连接采用fork分离进程,当客户端退出时,采用sigcation函数来销毁子进程,防止僵尸进程的产生。
服务器端代码如下:

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wait.h>
#include <signal.h>
using namespace std;

void read_childproc(int sig);
int main(int argc,char *argv[])
{

    int listenfd,connfd;
    sockaddr_in servaddr,cliaddr;
    char buf[4096];
    int recvNum;
    int addrLen=sizeof(servaddr);
    pid_t pid;
    struct sigaction act;
    if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        printf("socket error:%s:%d\n",strerror(errno),errno);
        exit(1);
    }   
    act.sa_handler=read_childproc;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    int state=sigaction(SIGCHLD,&act,0);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(6666);
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

    if((bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)))==-1)
         {
                  printf("bind error:%s:%d\n",strerror(errno),errno);
                  exit(1);
         }

    if((listen(listenfd,10))==-1)
          {
                  printf("listen error:%s:%d\n",strerror(errno),errno);
                  exit(1);
          }
    printf("=========waiting client's connection===========\n");
    while(1)
    {

        if((connfd=accept(listenfd,(struct sockaddr*)&cliaddr,(socklen_t *)&addrLen))==-1)
        {
             printf("connect error:%s:%d\n",strerror(errno),errno);
                     exit(1);

        }

        else
        {
             printf("client id:%d\n",connfd);
        }
        pid=fork();
        if(pid==-1)
        {
            close(connfd);
            continue;
        }
        if(pid==0)      /*子进程运行区域*/
        {       
            close(listenfd);
            while((recvNum=read(connfd,buf,1024))!=0)
            {
            write(connfd,buf,recvNum);
            std::cout<<buf<<pid<<std::endl;
            }
            close(connfd);
        }
        else
        {
            close(connfd);
        }
    }
    close(listenfd);
    return 0;
}
void read_childproc(int sig)
{
    pid_t pid;
    int status;
    pid=waitpid(-1,&status,WNOHANG);
    printf("removed proc id:%d\n",pid);
}

客户端代码:

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wait.h>
#include <signal.h>
void read_childproc(int sig);
int main(int argc,char *argv[])
{
    int connfd,state;
    sockaddr_in servaddr;
    struct sigaction act;
    char buf[4096];
    char msg[1024];
    int writeNum;

    if((connfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        printf("socket error:%s:%d",strerror(errno),errno);
        exit(1);
    }   
    act.sa_handler=read_childproc;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    state=sigaction(SIGINT,&act,0);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(6666);
    servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");



    if((connect(connfd,(struct sockaddr*)&servaddr,sizeof(servaddr)))==-1)
    {
             printf("connect error:%s:%d",strerror(errno),errno);
                     exit(1);
    }
    while(1)
    {
        fgets(msg,1024,stdin);
        if( (!strcmp(msg,"q\n")) ||(!strcmp(msg,"Q\n")))
        {
            shutdown(connfd,SHUT_WR);
            return 1;

        }
        writeNum=write(connfd,msg,sizeof(msg));
        read(connfd,buf,4096);
        buf[writeNum]=0;

        printf("send msg:%s",buf);
    }
    close(connfd);

    return 0;
}
void read_childproc(int sig)
{
    pid_t pid;
    int status;
    pid=waitpid(-1,&status,WNOHANG);
    printf("removed proc id:%d\n",pid);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值