使用多路复用实现客户端与客户端进行通信;
原理:客户端只要一连上服务器,立马给服务器发送用户名,然后在服务端将newsocketfd存放在同一个结构体中,客户端先给服务器发送数据,然后通过服务器转发给客户端。(服务器先会查找对应名字的newsocketfd 然后向该newsocketfd中写入数据)。
服务器端程序: #include<stdio.h> #include<netinet/in.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include<pthread.h> #include<strings.h> struct fd_info { int cfd; char cname[120]; }; void send1(struct fd_info a[]) { int i; char buf[50]; bzero(buf,50); fgets(buf,50,stdin); for(i=0;i<12;i++) { if(a[i].cfd !=0) send(a[i].cfd,buf,50,0); } } int main() { struct fd_info fds[12]; int maxfd = -1; int socketfd = socket(PF_INET,SOCK_STREAM,0); if(socketfd>maxfd) maxfd = socketfd; struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(6000); saddr.sin_addr.s_addr = inet_addr("192.168.1.46"); int newsocketfd; int n = 1; setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int)); if(bind(socketfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0) perror("bind() error! "); if(listen(socketfd,5)<0) perror("listen() error! "); struct sockaddr_in caddr; int s = sizeof(struct sockaddr); // newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s); fd_set fd; FD_ZERO(&fd); int ret; char buf[50],buf1[50]; int i; for(i=0;i<12;i++) { fds[i].cfd = 0; } char namebuf[120]; int rsize; char *split = ":"; char *token,*tokem,*tokeu; while(1) { FD_ZERO(&fd); FD_SET(0,&fd); FD_SET(socketfd,&fd); /*将新socket加入到fd_set中*/ for(i=0;i<12;i++) { // printf("-------------- "); if(fds[i].cfd!=0) FD_SET(fds[i].cfd,&fd); } /*监视老socketfd的状态是否改变,一旦改变说明有新的服务器连接进来 然后接受客户端发送过来的数据,并将其和newsocketfd存放于同一个结构体中*/ ret = select(maxfd+1,&fd,NULL,NULL,NULL); if(ret<0) { perror("select() error! "); break; } else if(ret ==0) { continue; } else { if(FD_ISSET(socketfd,&fd)) { newsocketfd = accept(socketfd,(struct sockaddr*)&caddr,&s); if(newsocketfd>maxfd) { maxfd = newsocketfd; recv(newsocketfd,namebuf,120,0); // printf("%s ",namebuf); for(i=0;i<12;i++) { if(fds[i].cfd==0) { fds[i].cfd = newsocketfd; strcpy(fds[i].cname,namebuf); printf("%s ",fds[i].cname); // printf("-------------- "); break; } } } continue; } // printf("helo "); /*将接受到的数据进行解析*/ for(i=0;i<12;i++) { if((fds[i].cfd !=0) && FD_ISSET(fds[i].cfd,&fd)) { bzero(buf1,50); if(recv(fds[i].cfd,buf1,50,0)==0) { //printf("core error! "); close(fds[i].cfd); // printf("core error! "); fds[i].cfd = 0; // printf("core error! "); break; } // printf("%s ",buf1); token = strtok(buf1,split); // printf("token=%s ",token); tokem = strtok(NULL,split); // printf("tokem=%s ",tokem); tokeu = strtok(NULL,split); // printf("tokeu=%s ",tokeu); /*判断是要给那个newsocketfd发送数据,然后将数据发送出去*/ for(i=0;i<12;i++) { // int flag; // printf("---- "); if(!strncmp(fds[i].cname,token,3)) { // printf("---- "); strcat(tokeu,":"); // printf("---- "); strcat(tokeu,tokem); printf("cname = %s ",fds[i].cname); // break; if(send(fds[i].cfd,tokeu,strlen(tokeu),0)<0) perror("send() error! "); // break; } else { // printf("this is not present! "); } } } continue; } /**给所有客户端发送数据*/ if(FD_ISSET(0,&fd)) { send1(fds); } } } close(socketfd); close(newsocketfd); } //客户端代码: #include<stdio.h> #include<pthread.h> #include<netinet/in.h> #include<stdlib.h> #include<string.h> #include<strings.h> #include<sys/types.h> #include<sys/socket.h> int main(int argc,char **argv) { int socketfd,ret; fd_set fd; FD_ZERO(&fd); FD_SET(0,&fd); socketfd = socket(PF_INET,SOCK_STREAM,0); FD_SET(socketfd,&fd); ret = select(socketfd+1,&fd,NULL,NULL,NULL); struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family = PF_INET; saddr.sin_port = htons(6000); saddr.sin_addr.s_addr = inet_addr("192.168.1.46"); if(connect(socketfd,(struct sockaddr *)&saddr,sizeof(struct sockaddr))<0) perror("connect() error! ");
//只要与服务器连上立马将自己的昵称发送过去 send(socketfd,argv[0],strlen(argv[0]),0); char buf[50],buf1[50]; while(1) { bzero(buf,50); bzero(buf1,50); FD_SET(0,&fd); FD_SET(socketfd,&fd); ret = select(socketfd+1,&fd,NULL,NULL,NULL); if(FD_ISSET(socketfd,&fd)) { if(recv(socketfd,buf1,sizeof(buf1),0)<0) perror("recv() error! "); printf("%s ",buf1); continue; } if(FD_ISSET(0,&fd)) { scanf("%s",buf); strcat(buf,":"); strcat(buf,argv[0]); if(send(socketfd,buf,strlen(buf),0)<0) perror("send() error! "); continue; } } }