Socket套接字编程(TCP并发服务器模型)

并发编程典型框架


服务器阻塞于accept函数调用,当客户端申请连接请求时客户端与服务器的状态


从accept函数返回后,新的连接被内核接受,创建新的connfd套接字


通过fork父进程可以创建子进程,让其代替自己完成读写数据操作


此时listenfd与connfd被父子进程所共享,接下来父进程关闭连接套接字只负责监听,但父进程可再次调用accept函数准备处理下一个客户端连接请求,而子进程关闭监听套接字只负责读写数据


服务器代码

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
int main(int argc,char * argv[])
{
    pid_t pid;
    int listenfd,connfd=0;
    char sendbuf[100]= {"success"},revbuf[100]= {};
    struct sockaddr_in ser,clt;
    socklen_t len=sizeof(clt);
    listenfd=socket(AF_INET,SOCK_STREAM,0);
    ser.sin_family = AF_INET;
    ser.sin_port = htons(8001);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    int optval=1;
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))< 0)
    {
        printf("setsockopt bind error!\n");
        exit(0);
    }
    if(bind(listenfd,(struct sockaddr*)&ser,sizeof(ser))<0)
    {
        printf("bind failed!\n");
        exit(0);
    }
    if(listen(listenfd,SOMAXCONN)<0)
    {
        printf("listen failed!\n");
        exit(0);
    }
    while(1)
    {
        connfd=accept(listenfd,(struct sockaddr*)&clt,(socklen_t *)&len);
        if(connfd==-1)
        {
            printf("connect failed!\n");
        }
        pid=fork();
        if(pid==0)
        {
            close(listenfd);
            printf("child process running\n");
            while(1)
            {
                int ret=read(connfd,revbuf,sizeof(revbuf));
                if(ret<0)
                {
                    printf("read failed!\n");
                    exit(0);
                }
                else if(ret==0)
                {
                    printf("client closed\n");
                    exit(0);
                }
                printf("server revmsg:%s\n",revbuf);
                write(connfd,sendbuf,sizeof(sendbuf));
                memset(revbuf,0,sizeof(revbuf));
            }
        }
        else if(pid>0)
        {
            close(connfd);
        }
        else
        {
            printf("create failed!\n");
            close(connfd);
            close(listenfd);
            exit(0);
        }
    }
    if(pid==0)
    {
        close(connfd);
    }
    else
    {
        close(listenfd);
    }
    return 0;
}

客户端代码

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
int main(int argc,char *argv[])
{
    struct sockaddr_in user;
    int sockfd;
    char sendbuf[100],revbuf[100];
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
    {
        printf("socket failed!\n");
        exit(0);
    }
    user.sin_family = AF_INET;
    user.sin_port = htons(8001);
    user.sin_addr.s_addr = inet_addr("127.0.0.1");
    if ( connect(sockfd, (struct sockaddr*) (&user), sizeof(user)) < 0)
    {
        perror("connect failed!\n");
        exit(0);
    }
    while(~scanf("%s",sendbuf))
    {
        write(sockfd,sendbuf,sizeof(sendbuf));
        read(sockfd,revbuf,sizeof(revbuf));
        printf("client revmsg:%s\n",revbuf);
        memset(sendbuf,0,sizeof(sendbuf));
        memset(sendbuf,0,sizeof(revbuf));
    }
    close(sockfd);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值