linuxC网络聊天室简单代码,CSDN博客迁移
学习总结:因为前一段对LINUX –C的学习也对网络编程有一点的认识,通过这一次聊天室的制作,更增加对学习新知识的兴趣。写聊天室时主要遇到的
问题是
1.服务器实现并发功能(接受和发送)
2.实现多客户端连接服务器。
3.怎样识别客户端之间的差别与联系
4.实现多客户端之间的接受和发送。
问题解决方案
1.实现并发服务,我主要用了线程进行接收,通过接收的信息在识别创建发送线程。在服务器主函数中主要管理客户端的连接。
2.在主函数中连接客户端主要是用数组贮存接收成功后(accept函数)的标识符,这样每个客户端都可连接,并且客户端可区分。
3.我用接收成功后的标识符和客户端的用户名进行客户端识别。
4.服务器通过客户端发送过来的字符串进行识别,发送的是个人还是群聊。
这次写的比较简单,代码还可以进行完善和功能添加。
服务器: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <string.h> #include <memory.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <error.h> #include <netinet/in.h> #include <arpa/inet.h> #include<termios.h> #define MAX_LINE 1024 #define MAX_CLIENT 15 char recvbuf[MAX_LINE]={0}; //传送内容缓冲区 int num=0; //客户端连接标记 char sendbuf[MAX_LINE]={0}; int client[MAX_CLIENT]; //FD_SETSIZE,1024是tcp最大连接数,client[FD_SETSIZE] 存放有数据请求的客户端; char name[15][1024]={0}; int FLACE=0; int findname(char *name1) { int i = 0; for(i=0;i<5;i++) { printf("name[%d]=%s\n",i,name[i]); } printf("find_name:%s",name1); for (i = 0; i < MAX_CLIENT; i++) { if (client[i]!=-1&&(strcmp((name[i]), name1))==0) return i; } return -1; } void sendto_one(int *client_num) { char buf[1024]={0}; char recvname[20] = { 0 }; char *p = strtok(sendbuf + 3, "\r\n");//TO:3个字符后取出\r\n前的名字 printf("(p)=%sa\n",p); strcpy(recvname, p); int sock= findname(recvname); if(sock==0) { memset(buf, 0,MAX_LINE); sprintf(buf,"此人没上线\n"); send(client[*client_num],buf,strlen(buf),0); } printf("(sock=)%d\n",sock); while(1) { if(sock!=-1&&num==1) { memset(buf, 0,MAX_LINE); sprintf(buf,"FPOM:%s\r\n%s",name[*client_num],sendbuf+4+strlen(p)+2); send(client[sock],buf,strlen(buf),0); printf("send success\n"); num=0; } } } void sendto_all(int *client_num) { int i,j; char buf[1024] = { 0 }; printf("send.buf=%s\n",sendbuf); memset(buf, 0,MAX_LINE); sprintf(buf, "FPOM:%s\n%s",name[*client_num],sendbuf); j=0; printf("sendto_all11.buf=%s\n",buf); for(i=0;i<15;i++) { printf("client[%d]=%d\n",i,client[i]); } while(1) { while(j<10) { if(client[j]!=-1&&num==1) { printf("name[j]%s",name[j]); send(client[j],buf,MAX_LINE,0); } printf("send to kehu\n"); j++; } num=0; } } void recvwhole(int* client_num) { int n; pthread_t tid2,tid3; while(1) { memset(recvbuf, 0,MAX_LINE);//初始化数组 n=0; n=recv(client[*client_num],recvbuf,MAX_LINE,0); if(n>0) { printf("(recv.buf=)%s\n",recvbuf); memset(sendbuf, 0,MAX_LINE);//初始化数组 strcpy(sendbuf,recvbuf); num=1; printf("(num=)%d,\n(sendbuf:)\n%s\n",num,sendbuf); } if (!strncmp(sendbuf, "TO:",3)) { printf("发送个人\n"); pthread_create(&tid2,NULL,(void*)sendto_one,(void*)client_num); pthread_detach(tid2); } if (!strncmp(sendbuf, "ALL\r\n", 5)) { printf("发送群体\n"); pthread_create(&tid3,NULL,(void*)sendto_all,(void*)client_num); pthread_detach(tid3); } } } int input_name(int *n) { int a,b; memset(sendbuf, 0,MAX_LINE); //sprintf(sendbuf,"请输入你的姓名:"); //a=send(client[*n],sendbuf,MAX_LINE,0); b=recv(client[*n],name[*n],MAX_LINE,0); printf("(name[%d]=)%s\n",*n,name[*n]); if(b>0) {return 0;} else { input_name(n); } } void *pthread_fun(int * client_num) { if(input_name(client_num)) { perror("input name fail");exit(-1); } char *p; pthread_t tid1,tid2,tid3; pthread_create(&tid1,NULL,(void*)recvwhole,/); pthread_detach(tid1); } int main(int argc,char *argv[]) { struct sockaddr_in addr;//保存客户端地址 socklen_t len; //保存客户端地址长度 struct sockaddr_in add2; int port=8800; char addr_p[INET_ADDRSTRLEN]; int i=0,ii; int lfd,cfd; //套接字 int a[15]; pthread_t tid1,tid2; //创建线程变量 bzero(&addr,sizeof(addr));//清空地址结构 addr.sin_family=AF_INET;//使用IP4 addr.sin_port=htons(port);//端口号 addr.sin_addr.s_addr=INADDR_ANY;//服务器可以接受任意地址 for(i=0;i<MAX_CLIENT;i++) { client[i]=-1;} //1 if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("fail to socket");exit(1); } printf("创建套接字成功\n"); //设置端口可重用 int opt = 1; setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //将套接字绑定到服务器的网络地址上 //2 if(bind(lfd,(struct sockaddr*)&addr,sizeof(addr))==-1) { perror("fial to bind");exit(1); } printf("绑定地址套接字成功\n"); //3 if (listen(lfd, 10) == -1) { perror("fail to listen"); exit(1); } printf("监听成功\n"); i=0; while(i<MAX_CLIENT) { ii=i; len=sizeof(add2); client[i]=accept(lfd,(struct sockaddr*)&add2,&len); //printf("\n**%d\n",client[i]); printf("接受成功,i = %d\n",i); printf("create thread\n"); a[i]=i; if(pthread_create(&tid1,NULL,(void*)pthread_fun,&a[i])!=0) { perror("create success");exit(-1); } pthread_detach(tid1); i++; if(ii<i) { inet_ntop(AF_INET,&addr.sin_addr,addr_p,sizeof(addr_p));////将客户端地址转换为字符串 printf("IP=%s,port=%d\n",addr_p,ntohs(addr.sin_port)); }
客户端: #include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #define MAX_LINE 1024 char buf[MAX_LINE]; int port=8800; char name[200]={0}; int FLACE=0; void fun_all(int sockfd) { char sendbuf[1024]={0}; sprintf(sendbuf,"ALL\r\n",5); printf("\n");getchar(); printf("输入聊天内容:\n"); fgets(sendbuf+strlen(sendbuf),100,stdin); //scanf("%s",sendbuf+5); //sprintf(sendbuf+strlen(sendbuf),"\n"); printf("(all sendbuf)=%s\n",sendbuf); if(send(sockfd,sendbuf,strlen(sendbuf),0)<=0) { printf("send error\n");close(sockfd);exit(1); } } void fun_one(int sockfd) { char sendbuf[1024] = {0}; char name3[20] ; printf("输入聊天对象:");getchar(); memset(name3,0,20); fgets(name3,20,stdin); printf("(name3)\n%s",name3); sprintf(sendbuf,"TO:%s\r\n",name3); printf("输入聊天内容:\n"); fgets(sendbuf+strlen(sendbuf),100,stdin); //printf("(sendbuf)=%s\n",sendbuf); //sprintf(sendbuf+strlen(sendbuf),"\r"); if(send(sockfd,sendbuf,strlen(sendbuf),0) <= 0) { printf("send err\n"); close(sockfd); exit(1); } } void menu() { printf("^^^^^^^^^^^^^^^^^^^^\n"); printf("1.私聊模式(发送to)\n"); printf("2.群聊模式(发送all)\n"); printf("~~~~~~~~~~~~~~~~~~~~\n"); } void *fun(int *sock) { int sockfd=*sock; int n; char *p,*q; char name2[20]={0}; while(1) { n=0; memset(buf,0,MAX_LINE);//初始化数组 n=recv(sockfd,buf,MAX_LINE,0); if(n>0) { printf("\n\n接受到:"); printf("\n*************\n%s******************\n",buf); } if(n<=0) { printf("recv failed\n"); exit(1); } } } int main(int argc,char *argv[]) { int l_fd;//套接字 struct sockaddr_in addr; char sendbuf[1024] = {0}; char str[6] = {0}; int n; pthread_t pid1; bzero(&addr,sizeof(addr)); addr.sin_family=AF_INET; inet_pton(AF_INET,"10.25.100.*",&addr.sin_addr); addr.sin_port=htons(port); if((l_fd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("fail to creat socket");exit(1); } printf("创建套接字成功\n"); if(connect(l_fd,(struct sockaddr *)&addr,sizeof(addr)) == -1) { perror("fail to connect");exit(1); } printf("connect success\n"); memset(name,0,20); printf("请输入你的姓名:"); scanf("%s",name); sprintf(sendbuf,name); //把格式化的数据写入某个字符串,"LOGIN\r\n%s\r\n\r\n" send(l_fd,sendbuf,strlen(sendbuf),0); //printf("sendbuf=%s\n",sendbuf); pthread_create(&pid1,NULL,(void*)fun,(void*)&l_fd); pthread_detach(pid1); while(1) { menu(); memset(str,0,6); scanf("%s",str); if(!strcmp(str,"all")) { printf("群聊模式\n"); fun_all(l_fd); continue; } else if(!strcmp(str,"to")) { printf("私聊模式\n"); fun_one(l_fd); continue; } else printf("请重新输入:"); } wait(NULL); close(l_fd); return 0; } } return 0; }
每一成功的背后都有个人的努力和家人的支持