您的位置:首页 > 理论基础 > 计算机网络

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

2017-09-26 00:18 435 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: