unix 网络编程---select回射TCP,UDP

Client:这里是MAC os运行测试的,Linux  FD_SET函数是可以通用的

#include <stdio.h>

#include <sys/socket.h>

#include <sys/select.h>

#include <sys/types.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#include <string.h>

#include <stdlib.h>

#include <netdb.h>

#include <time.h>

#include <errno.h>

#include <unistd.h>

#include <sys/select.h>

#define PORT 34560

#define  MAX 100

const char * end="quit\n";

void err_quit(const char *s)

{

    puts(s);

    exit(0);

}

int Max(const int a,const int b)

{

    return a>b?a:b;

}

void str_cli(const int con,FILE *fp)

{

    char sen[MAX],rec[MAX];

    int num,maxfd,nread;

    fd_set rset;

    __DARWIN_FD_ZERO(&rset);

    memset(sen, 0, MAX);

    memset(rec, 0, MAX);

    while(1)

    {

        __DARWIN_FD_SET(con, &rset);

        __DARWIN_FD_SET(fileno(fp), &rset);

        maxfd=Max(fileno(fp), con)+1;

        nread=select(maxfd, &rset, NULL, NULL, NULL);

        if(nread<=0)

            err_quit("accept error!");

        if(__DARWIN_FD_ISSET(con, &rset))

        {

            num=(int)recv(con, rec, MAX, 0);

            rec[num]='\0';

            fprintf(stdout, "recviev from server %s\n",rec);

            if(num<=0||num>MAX)

                err_quit("data is error!");

        }

        if(__DARWIN_FD_ISSET(fileno(fp), &rset))

        {

            if(fgets(sen,MAX,fp)==NULL)

                err_quit("nothing sends to server");

            printf("\n");

            send(con, sen, MAX, 0);

            if(strcmp(end, sen)==0)

                err_quit("client is over!");

        }

    }

}

void setInitialServer(struct sockaddr_in * server)

{

    bzero(server, sizeof(*server));

    server->sin_family=AF_INET;

    server->sin_port=htons(PORT);

    server->sin_addr.s_addr=inet_addr("127.0.0.1");

}

int Connection(const int A,const struct sockaddr *server ,socklen_t size)

{

    int con;

    con=connect(A, server, size);

    if(con==-1)

        err_quit("connection is error");

    return con;

}

int main(int argc, const char * argv[]) {

    // insert code here...

    struct sockaddr_in server,client;

    int sockfd;

    socklen_t len=sizeof(client);

    sockfd=socket(AF_INET, SOCK_STREAM, 0);

    if(sockfd==-1)

        err_quit("socket error!");

    setInitialServer(&server);

    Connection(sockfd, (struct sockaddr *)&server, len);

        str_cli(sockfd, stdin);

    return 0;

}

//服务器:

#include <stdio.h>

#include <sys/socket.h>

#include <unistd.h>

#include <sys/select.h>

#include <sys/types.h>

#include <time.h>

#include <sys/time.h>

#include <string.h>

#include <arpa/inet.h>

#include <errno.h>

#include <netinet/in.h>

#include <stdlib.h>

#include <signal.h>

#define MAX 100

#define PORT 34560

#define LAN 5

const char * end="quit\n";

void funct(int sign);

/*

   子进程出错返回的状态等显示函数

 */

void err_child_progress(const int status)

{

    if(WIFEXITED(status))

    {

        fprintf(stdout,"其终止状态是按照正常终止的\n" );

        return;

    }

    else if(WIFSIGNALED(status))

    {

        printf("异常终止,终止的信号的编号是%d\n",WTERMSIG(status));

        return;

    }

    else if(WIFSTOPPED(status))

    {

        printf("当前暂停子进程,子进程暂停编号是:%d\n",WSTOPSIG(status));

        return ;

    }

}

void err_quit(const char *s)

{

    puts(s);

    exit(0);

}

int MAX_Variable(const int a,const int b)

{

    return a>b?a:b;

}

int Socket(const int AF,const int SO,const int a)

{

    int sockfd;

    sockfd=socket(AF,SO,a);

    if(sockfd==-1)

        err_quit("socket error!");

    return sockfd;

}

int Bind(const int Sockfd,const struct sockaddr *server,socklen_t len)

{

    int bin;

    bin=bind(Sockfd, server, len);

    if(bin==-1)

        err_quit("bind error!");

    return bin;

}

int Listen(const int sockfd,const int lan)

{

    int listened;

    listened=listen(sockfd, lan);

    if(listened==-1)

        err_quit("listen error");

    return listened;

}

void ControlingStringsTCP(const int con)

{

    /*

     防止服务器主机出现sigpipe信号的出现,造成服务器关闭,我们的设计就应该考虑的是用select函数防止服务器关闭出现。

     这样的情况是:一个进程向一个已收到RST的套接字上执行写操作内核就会发送一个sigpipe信号,终止信号。其捕获后应该做的是不加任何处理signal(sigpipe,sig_ign);返回的errno==EPiPE的

     

     

     */

    

    

    char sen[MAX],rec[MAX];

    int num,i,j;

    memset(sen, 0, MAX);

    memset(rec,0,MAX);

    while((num=(int)read(con, rec, MAX))>0)

    {

        puts("-------------TCP--------------");

        rec[num]='\0';

        fprintf(stdout, "recviev from client is %s\n",rec);

        if(strcmp(end, rec)==0)

        {

            puts("server is ending!");

            exit(0);

        }

        if(num>MAX)

            err_quit("too many data!");

        j=(int)strlen(rec);

        for(i=0;i<j;i++)

            sen[j-i-1]=rec[i];

        sen[j]='\0';

        write(con, sen, MAX);

        printf("send to client is %s\n",sen);

    }

}

void ContorllingstringsUDP(const int udp,struct sockaddr * client,socklen_t len)

{

    char sen[MAX],rec[MAX];

    int num,i,j;

    memset(sen, 0, MAX);

    memset(rec,0,MAX);

    while((num=(int)recvfrom(udp, rec, MAX, 0, client, &len))>0)

    {

        puts("------------UDP-------------");

        printf("udp is ok ,length of udp is %d\n",client->sa_len);

        rec[num]='\0';

        j=(int)strlen(rec);

        if(num>MAX)

            err_quit("too many data!");

        if(strcmp(end, rec)==0)

        {

            puts("UDPserver is ending!");

            exit(0);

        }

        j=(int)strlen(rec);

        for(i=0;i<j;i++)

            sen[j-i-1]=rec[i];

        sen[j]='\0';

        sendto(udp, sen, MAX, 0, client, len);

        printf("send to client is %s\n",sen);

    }

}

void funct(int sign)

{

    int status;

    while(waitpid(-1, &status, WNOHANG) > 0);

    err_child_progress(status);

    return ;

}

int main(int argc, const char * argv[]) {

    // insert code here...

    int sockfd,conn,opt=1,udpf,maxfd,nready;

    struct sockaddr_in server,client;

    socklen_t len=sizeof(client);

    fd_set rset;

    __DARWIN_FD_ZERO(&rset);

    

    sockfd=Socket(AF_INET, SOCK_STREAM, 0);

    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR , &opt, sizeof(opt));

    bzero(&server, sizeof(server));

    server.sin_family=AF_INET;

    server.sin_port=htons(PORT);

    server.sin_addr.s_addr=htonl(INADDR_ANY);

    Bind(sockfd, (struct sockaddr*)&server, sizeof(server));

    Listen(sockfd, LAN);

    udpf=Socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&server, sizeof(server));

    server.sin_family=AF_INET;

    server.sin_port=htons(PORT);

    server.sin_addr.s_addr=htonl(INADDR_ANY);

    setsockopt(udpf,SOL_SOCKET,SO_REUSEADDR , &opt, sizeof(opt));

    Bind(udpf,(struct sockaddr*)&server, sizeof(server));

    signal(SIGCHLD, funct);

    maxfd=MAX_Variable(sockfd, udpf)+1;

    while(1)

    {

        __DARWIN_FD_SET(sockfd, &rset);

        __DARWIN_FD_SET(udpf, &rset);

        nready=select(maxfd, &rset, NULL, NULL, NULL);

        if(nready<0)

        {

            if(errno==EINTR)

                continue;

            else

                err_quit("select error");

        }

        if(__DARWIN_FD_ISSET(sockfd, &rset))

        {

         /*

          tcp mutilprocessProgram; parent ID means listen client,

          and child ID control the strings ,including recviev from client information and perversion dispose strings,do send to clients' message!

          */

            conn=accept(sockfd, (struct sockaddr*)&client, &len);

            if(conn<0)

            {

               if(errno==EINTR)

                   continue;

                /*

                 防止慢系统调用来将accept函数进行中断处理,其返回是有可能会出现一个EINTR错误回来,有可能系统内核会进行系统中断的调用。

                 我这样就可以用来捕获其返回的中断出错的错误时候,continue保证系统的继续运行

                 */

                else

                    err_quit("accept error!");

            }

            printf("family is TCP,Client is %s,ip is %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));

            pid_t pid=fork();

            if(pid==0)

            {

                close(sockfd);

                ControlingStringsTCP(conn);

                exit(0);

            }

            close(conn);

        }

        if(__DARWIN_FD_ISSET(udpf,&rset))

        {

            ContorllingstringsUDP(udpf, (struct sockaddr *)&client, len);

        }

    }

    return 0;

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值