云计算百科
云计算领域专业知识百科平台

网络编程之客户端通过服务器与另外一个客户端交流

服务器使用select模型搭建,客户端1使用线程搭建,客户端2使用poll模型搭建,

使用时需要先运行服务器,具体编译可看我最后的图片

 head.h头文件

#ifndef __HEAD_H_ #define __HEAD_H_

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/stat.h> #include <pwd.h> #include <dirent.h> #include <wait.h> #include <errno.h> #include <pthread.h> #include <semaphore.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>  #include <poll.h> #include <signal.h> #define PRINTF_ERROR(a) {perror(a);return -1;} #endif

 服务器搭建代码

server_select.c

#include <head.h> enum Type{     TYPE_LOGIN,     TYPE_REDIST }; typedef struct Pack{ //协议包     int packsize;     enum Type type;     char buf[4096];     int used;

}pack_t;    void freeList(char** list){     for(int i=0;list[i]!=NULL;i++){         free(list[i]);     }     free(list); }

char** analysis(pack_t pack){     //解析客户端发来的协议包     char* buf=pack.buf;     int readed_size=0;     char** list = calloc(1,80);     int i=0;//     while(1){         short size = *(short*)(buf+readed_size);         if(size==0)             break;         readed_size+=2;         char temp[size+1];         memset(temp,0,size+1);         memcpy(temp,buf+readed_size,size);         readed_size+=size;

        list[i]=calloc(1,size+1);         strcpy(list[i],temp);         i++;     }     return list;

} void insert_client(int* arr,int client,int* len){ //将客户端的描述符放入数组     arr[*len]=client;     (*len)++; } void remove_client(int* arr,int client,int* len){     int i=0,j=0;     for(i=0;i<*len;i++){         if(arr[i]==client)             break;     }     if(i==*len)         return;     for(j=i;j<*len;j++){         arr[j]=arr[j+1];     }     arr[j]=0;     (*len–); } int main(int argc, const char *argv[]) {     if(argc<2){         printf("请输入端口号:\\n");         return 1;     }     int port = atoi(argv[1]);     int server = socket(AF_INET,SOCK_STREAM,0);     struct sockaddr_in addr = {0};

    addr.sin_family = AF_INET;     addr.sin_port = htons(port);     addr.sin_addr.s_addr = inet_addr("0.0.0.0");     if(bind(server,(struct sockaddr*)&addr,sizeof(addr))==-1){         perror("bind");         return -1;     }     listen(server,50);

    int  client_arr[64]={0};//存放所有客户端套接字的数组     int arr_len=0;//记录数组的长度     fd_set readfds;//创建一个select的监听列表     FD_ZERO(&readfds);//初始化监听列表     FD_SET(server,&readfds);//将服务器套接字放入监听列表中     FD_SET(STDIN_FILENO,&readfds);//将标准输入流放入监听列表中

    while(1){         fd_set temp=readfds;         select(1024,&temp,0,0,0);         if(FD_ISSET(0,&temp)){  输入流激活             char buf[1024]="";             scanf("%s",buf);             getchar();             printf("键盘输入数据:%s\\n",buf);         }         if(FD_ISSET(server,&temp)){  服务器激活             int client=accept(server,0,0);             printf("有客户端链接\\n");             FD_SET(client,&readfds);             insert_client(client_arr,client,&arr_len);         }         for(int i=0;i<arr_len;i++){             int client = client_arr[i];             if(FD_ISSET(client,&temp)){ //客户端激活

                pack_t pack={0};                 int size=0;                 int res=read(client,&size,4);                 if(res ==0){                     printf("客户端断开链接\\n");                     FD_CLR(client,&readfds);                     remove_client(client_arr,client,&arr_len);                     close(client);                     break;                 }                 pack.packsize=size;                 read(client,(char*)&pack+4,size-4);                 char** list=analysis(pack);                 for(int j=0;j<arr_len;j++){                         if(client_arr[i]!=client_arr[j]){                         if(write(client_arr[j],&pack,size)<=0)                             PRINTF_ERROR("write error");                     }                 }                 printf("%s\\n",list[0]);                 freeList(list);

            }         }     }     return 0; }

 客户端1

client1.c

#include <head.h> #include <pthread.h> enum Type{     TYPE_REGIST,     TYPE_LOGIN };

typedef struct Pack{     int packsize;     enum Type type;     char buf[4096];     int used; }pack_t;

void append(pack_t* pack,const char* str){     char* buf=pack->buf;     short size=strlen(str);     *(short*)(buf+pack->used)=size;     pack->used+=2;     memcpy(buf+pack->used,str,size);     pack->used+=size;     pack->packsize=pack->used+8; } void freeList(char** list){     for(int i=0;list[i]!=NULL;i++){         free(list[i]);     }                                                       free(list); }

char** analysis(pack_t pack){     char* buf=pack.buf;     int readed_size=0;     char** list = calloc(1,80);     int i=0;//     while(1){         short size = *(short*)(buf+readed_size);         if(size==0)             break;         readed_size+=2;         char temp[size+1];         memset(temp,0,size+1);         memcpy(temp,buf+readed_size,size);         readed_size+=size;

        list[i]=calloc(1,size+1);         strcpy(list[i],temp);         i++;     }     return list;

}

void* Write(void* arg){     int client =*(int *)arg;     while(1){         char str[20]="";         pack_t pack={0};         pack.type=TYPE_REGIST;         scanf("%19s",str);         getchar();         append(&pack,str);         write(client,&pack,pack.packsize);     }     pthread_exit(NULL);

} void* Read(void* arg){     int client =*(int *)arg;     while(1){         pack_t pack1={0};         int size=0;         read(client,&size,4);         read(client,(char*)&pack1+4,size-4);         char** list=analysis(pack1);         printf("客户端1:%s\\n",list[0]);              freeList(list);

    }     pthread_exit(NULL); } int main(int argc, const char *argv[]) {     if(argc<2){         printf("请输入端口号\\n");         return -1;     }     int port=atoi(argv[1]);     int client=socket(AF_INET,SOCK_STREAM,0);

    struct sockaddr_in addr={0};     addr.sin_family=AF_INET;     addr.sin_port=htons(port);     addr.sin_addr.s_addr=inet_addr("0.0.0.0");     if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1){         PRINTF_ERROR("bind error");     }

    pthread_t tid1,tid2;     pthread_create(&tid1,NULL,Write,&client);     pthread_create(&tid2,NULL,Read,&client);     pthread_join(tid1,NULL);     pthread_join(tid2,NULL);

    return 0; }

客户端2

client2.c

#include <head.h> enum Type{     TYPE_LOGIN,     TYPE_REDIST }; typedef struct Pack{     int packsize;     enum Type type;     char buf[4096];     int used;

}pack_t; void append(pack_t* pack,const char* str){     char* buf = pack->buf;     short size = strlen(str);     *(short*)(buf+pack->used) = size;     pack->used +=2;     memcpy(buf+pack->used,str,size);     pack->used+=size;     pack->packsize=pack->used+8; } // 该函数功能为:将client存入数组arr中的最后一个下标位置上,存完之后,arr数组的长度记得自增 void insert_client(struct pollfd* arr,struct pollfd client,int* len){     arr[*len] = client;     (*len)++; }

// 将client从数组arr中移除,移除后记得数组长度-1 void remove_client(struct pollfd* arr,int client,int* len){     int i = 0,j = 0;     for(i=0;i<*len;i++){         if(arr[i].fd == client){break;}     }                                                                                            if(i == *len){return;}     for(j=i;j<*len-1;j++){         arr[j] = arr[j+1];     }     //arr[j] = 0;     (*len)–; } void freeList(char** list){     for(int i=0;list[i]!=NULL;i++){         free(list[i]);     }     free(list); }

char** analysis(pack_t pack){     char* buf=pack.buf;     int readed_size=0;     char** list = calloc(1,80);     int i=0;//     while(1){         short size = *(short*)(buf+readed_size);         if(size==0)             break;         readed_size+=2;         char temp[size+1];         memset(temp,0,size+1);         memcpy(temp,buf+readed_size,size);         readed_size+=size;

        list[i]=calloc(1,size+1);         strcpy(list[i],temp);         i++;     }     return list;

}

int main(int argc, const char *argv[]) {     if(argc<2){         printf("请输入端口号:\\n");         return 1;                        }     int port = atoi(argv[1]);

    int client = socket(AF_INET,SOCK_STREAM,0);     struct sockaddr_in addr = {0};     addr.sin_family = AF_INET;     addr.sin_port = htons(port);     addr.sin_addr.s_addr = inet_addr("0.0.0.0");     if(connect(client,(struct sockaddr*)&addr,sizeof(addr))==-1){         perror("connect");         return -1;     }

    struct pollfd list[50]={0};     int list_len=0;     struct pollfd client_fd={fd:client,events:POLLIN,revents:0};     struct pollfd stdin_fd={fd:0,events:POLLIN,revents:0};

    insert_client(list,client_fd,&list_len);

    insert_client(list,stdin_fd,&list_len);

    while(1){

        poll(list,list_len,-1);         int i=0;         for(i=0;i<list_len;i++){             if(list[i].revents==0){                 continue;             }             int fd=list[i].fd;             if(fd==0){                 char str[20]="";                 pack_t pack = {0};                 pack.type=TYPE_REDIST;                 scanf("%19s",str);                 getchar();                 append(&pack,str);                 write(client,&pack,pack.packsize);             }else{                 pack_t pack1={0};                 int size=0;                 read(client,&size,4);                 read(client,(char*)&pack1+4,size-4);                 char** list=analysis(pack1);                 printf("客户端2:%s\\n",list[0]);                 freeList(list);

            }         }     }

    return 0; }

 结果

赞(0)
未经允许不得转载:网硕互联帮助中心 » 网络编程之客户端通过服务器与另外一个客户端交流
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!