【网络编程】学习笔记--04 server端和client代码

Server端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>

#define SERV_PORT 9527

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    int lfd = 0,cfd = 0;
    int ret,i;
    char buf[BUFSIZ],client_IP[BUFSIZ];

    struct sockaddr_in serv_addr,clit_addr;
    socklen_t clit_addr_len;

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);


    lfd = socket(AF_INET,SOCK_STREAM,0);
    if(lfd==-1){
        sys_err("socket error");
    }

    bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

    listen(lfd,128);

    clit_addr_len = sizeof(clit_addr);

    cfd = accept(lfd,(struct sockaddr *)&clit_addr,&clit_addr_len);
    if(cfd==-1){
        sys_err("accept error");
    }
    printf("client ip:%s port:%d\n",
            inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),
            ntohs(clit_addr.sin_port));

    while(1){
        ret = read(cfd,buf,sizeof(buf));

        for(i=0;i<ret;i++)
            buf[i]=toupper(buf[i]);
        write(STDOUT_FILENO,buf,ret);
    }
    close(lfd);
    close(cfd);
    return 0;
}
View Code

 

Client端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>

#define SERV_PORT 9527

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    int cfd;
    int conter=10;
    char buf[BUFSIZ];
        
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);

    inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr.s_addr);

    cfd = socket(AF_INET,SOCK_STREAM,0);
    if(cfd==-1)
        sys_err("socket error");

    int ret = connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    if(ret!=0)
        sys_err("connect error");

    while(conter--)
    {
        ret = read(STDIN,buf,sizeof(buf));
        write(cfd,buf,ret)
        write(STDOUT_FILENO,buf,ret);
        sleep(1);
    }
    close(cfd);

    return 0;
}
View Code

 

运行的时候,开2个窗口,一个窗口跑server端,./server即可,另一个跑client端,./client即可。注意要先编译。

 

多进程+回收子进程(信号捕捉杀僵尸进程)版server:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<sys/wait.h>
#include<sys/types.h>

#define SRV_PORT 9999

void catch_child(int signum)
{
    while(waitpid(0,NULL,WNOHANG)>0);
    return ;
}
int main(int argc,char *argv[])
{
    int lfd,cfd;
    pid_t pid;
    struct sockaddr_in srv_addr,clt_addr;
    socklen_t clt_addr_len;
    char buf[BUFSIZ];
    int ret,i;

    memset(&srv_addr,0,sizeof(srv_addr));

    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(SRV_PORT);
    srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = socket(AF_INET,SOCK_STREAM,0);

    bind(lfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));

    listen(lfd,128);

    clt_addr_len = sizeof(clt_addr);

    while(1){

        cfd = accept(lfd,(struct sockaddr *)&clt_addr ,&clt_addr_len);
        pid = fork();
        if(pid == 0){
            close(lfd);
            break;    
        }
        else if(pid > 0){
            struct sigaction act;
            act.sa_handler = catch_child;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            ret = sigaction(SIGCHLD,&act,NULL);
            
            close(cfd);
        }
    }

    if(pid == 0){
        for(;;){
            ret = read(cfd, buf ,sizeof(buf));
            if(ret == 0){
                close(cfd);
                exit(1);
            }

            for(i=0;i<ret;i++)
                buf[i]=toupper(buf[i]);
            write(cfd,buf,ret);
            write(STDOUT_FILENO,buf,ret);
        }
    }
    return 0;
}
View Code

 

多进程+回收子进程+端口复用版server:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<sys/wait.h>
#include<sys/types.h>

#define SRV_PORT 9999

void catch_child(int signum)
{
    while(waitpid(0,NULL,WNOHANG)>0);
    return ;
}
int main(int argc,char *argv[])
{
    int lfd,cfd;
    pid_t pid;
    struct sockaddr_in srv_addr,clt_addr;
    socklen_t clt_addr_len;
    char buf[BUFSIZ];
    int ret,i;

    memset(&srv_addr,0,sizeof(srv_addr));

    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(SRV_PORT);
    srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = socket(AF_INET,SOCK_STREAM,0);
    
    int opt=1;
    setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt))
    bind(lfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));

    listen(lfd,128);

    clt_addr_len = sizeof(clt_addr);

    while(1){

        cfd = accept(lfd,(struct sockaddr *)&clt_addr ,&clt_addr_len);
        pid = fork();
        if(pid == 0){
            close(lfd);
            break;    
        }
        else if(pid > 0){
            struct sigaction act;
            act.sa_handler = catch_child;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            ret = sigaction(SIGCHLD,&act,NULL);
            
            close(cfd);
        }
    }

    if(pid == 0){
        for(;;){
            ret = read(cfd, buf ,sizeof(buf));
            if(ret == 0){
                close(cfd);
                exit(1);
            }

            for(i=0;i<ret;i++)
                buf[i]=toupper(buf[i]);
            write(cfd,buf,ret);
            write(STDOUT_FILENO,buf,ret);
        }
    }
    return 0;
}
View Code

 

运用select的(可以不用写多进程)的server:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>

#define SERV_PORT 9527

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc,char *argv[])
{
    int listenfd = 0,connfd = 0;
    char buf[BUFSIZ];

    struct sockaddr_in serv_addr,clie_addr;
    socklen_t clie_addr_len;
    
    listenfd = socket(AF_INET,SOCK_STREAM,0);

    int opt = 1;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(listenfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    listen(listenfd,128);

    fd_set rset,allset;                 //定义读集合rset,备份集合allset
    int ret,maxfd = 0,n,i,j;
    maxfd = listenfd;                   //最大文件描述符

    FD_ZERO(&allset);                   //清空监听集合
    FD_SET(listenfd,&allset);           //将待监听fd添加到监听集合中

    while(1){
        rset = allset;                  //备份
        ret = select(maxfd+1, &rset, NULL, NULL,NULL);  //使用select监听
        
        if(FD_ISSET(listenfd,&rset)){               //listenfd满足监听读事件
            clie_addr_len = sizeof(clie_addr);
            connfd = accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len); //与客户端建立连接,不会阻塞

            FD_SET(connfd, &allset);        //将新产生的fd添加到监听集合中,监听数据读事件
            if(maxfd < connfd)              //修改maxfd
                maxfd = connfd;

            if(ret == 1)                    //说明select返回值只有1个,并且是listenfd,后续无需执行
                continue;
        }
        for(i = listenfd+1; i<=maxfd; i++){     //处理满足读事件的fd
            if(FD_ISSET(i,&rset)){              //找到满足读事件的fd
                n = read(i,buf,sizeof(buf));
                if(n == 0){                     //检测到客户端已经关闭连接
                    close(i);
                    FD_CLR(i,&allset);          //将关闭的fd移除出监听集合
                }

                for(j = 0; j < n;j++)
                    buf[j] = toupper(buf[j]);

                write(i,buf,n);
                write(STDOUT_FILENO,buf,n);
            }
        }
    }
    close(listenfd);
    return 0;
}
View Code

 

posted @ 2021-11-11 19:44  Anonytt  阅读(163)  评论(0编辑  收藏  举报