文章标题
来源:互联网 发布:sql exists in 效率 编辑:程序博客网 时间:2024/06/10 19:50
linux socket c/c++ 聊天
client_chat.c
#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>#include <malloc.h>#define MAXDATASIZE 256 //#define SERVPORT 4444 //服务器监听端口号#define STDIN 0 //标准输入文件描述符int main(int argc,char *argv[]){ char addr[30]; int sockfd; struct sockaddr_in serv_addr;//Internet套接字地址结构 char buf[MAXDATASIZE]; //用于处理输入的缓冲区 char name[MAXDATASIZE]; char send_str[MAXDATASIZE]; //最多发送的字符不能超过256 int recvbytes; fd_set rfd_set,wfd_set,efd_set; //select()监视读、写、异常处理的文件描述符集合 struct timeval timeout; //本次select()的超时结束时间 int ret; //与server连接的结果 if(argc<2) { printf("请输入服务器IP\n"); fgets(addr,256,stdin); argv[1] = (char *)malloc(sizeof(argv[1])); strcpy(argv[1],addr); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socker error!"); exit(1); } //填充sockaddr结构 bzero(&serv_addr,sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERVPORT); serv_addr.sin_addr.s_addr = inet_addr(argv[1]); if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))==-1) { perror("connect error!"); exit(1); } printf("已成功连接到服务器 %s\n",inet_ntoa(serv_addr.sin_addr)); fcntl(sockfd,F_SETFD,O_NONBLOCK);//服务器设为非阻塞 printf("要聊天首先要输入你的名字:"); scanf("%s",name); name[strlen(name)] = '\0'; printf("%s:",name); fflush(stdout); send(sockfd,name,strlen(name),0);//发送用户名到sockfd while(1) { //将select()监视的读,写,异常文件描述符清除 FD_ZERO(&rfd_set); FD_ZERO(&wfd_set); FD_ZERO(&efd_set); //将标准输入文件描述符加到select()监视的读文件描述符集合中 FD_SET(STDIN,&rfd_set); //添加新建的描述符加到select()监视的文件描述符中 FD_SET(sockfd,&rfd_set); // FD_SET(sockfd,&wfd_set); FD_SET(sockfd,&efd_set); //设置select在被监视窗口等待的时间 timeout.tv_sec = 10; //秒 timeout.tv_usec = 0; //微妙 ret = select(sockfd+1,&rfd_set,&wfd_set,&efd_set,&timeout); if(ret==0) continue; if(ret<0) { perror("select error!"); exit(-1); } //判断是否已将标准输入文件描述符加到select()监视的读的文件描述符集合中 if(FD_ISSET(STDIN,&rfd_set)) { fgets(send_str,256,stdin);//读取键盘输入的内容 send_str[strlen(send_str)-1] = '\0'; if(strncmp("quit",send_str,4)==0) { close(sockfd); exit(0); } send(sockfd,send_str,strlen(send_str),0); } //判断是否已将新建的描述符加到select()监视的读的文件描述符集合中 if(FD_ISSET(sockfd,&rfd_set)) { recvbytes = recv(sockfd,buf,MAXDATASIZE,0); if(recvbytes==0) { close(sockfd); exit(0); } buf[recvbytes] = '\0'; printf("Server: %s\n",buf); printf("%s: ",name); fflush(stdout); } //异常 if(FD_ISSET(sockfd,&efd_set)) { close(sockfd); exit(0); } } return 0;}
server_chat.c
#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>#define MAXDATASIZE 256 //#define SERVPORT 4444 //服务器监听端口号#define BACKLOG 10 //最大连接请求数#define STDIN 0 //标准输入文件描述符int main(void){ FILE *fp; int sockfd,client_fd; int sin_size; struct sockaddr_in my_addr,remote_addr;//本机地址信息,客户机地址信息 char buf[256]; //用于聊天的缓冲区 char buff[256]; //用于输入用户名的缓冲区 char send_str[256]; //最多发送的字符不能超过256 int recvbytes; fd_set rfd_set,wfd_set,efd_set; //select()监视读、写、异常处理的文件描述符集合 struct timeval timeout; //本次select()的超时结束时间 int ret; //与client连接的结果 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socker error!"); exit(1); } //填充sockaddr结构 bzero(&my_addr,sizeof(struct sockaddr_in)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(SERVPORT); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //解决服务器关掉,启动“Address already in use”的情况 int on=1; setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))==-1) { perror("bind error!"); exit(1); } if(listen(sockfd,BACKLOG)==-1) { perror("listen error!"); exit(1); } sin_size = sizeof(struct sockaddr_in); if((client_fd=accept(sockfd,(struct sockaddr*)&remote_addr,&sin_size))==-1) { perror("accept error!"); exit(1); } printf("收到一个连接来自: %s\n",inet_ntoa(remote_addr.sin_addr)); fcntl(client_fd,F_SETFD,O_NONBLOCK);//服务器设为非阻塞 recvbytes = recv(client_fd,buff,MAXDATASIZE,0); buff[recvbytes] = '\0'; fflush(stdout); if((fp=fopen("name.txt","a+"))==NULL) { printf("cannot open file,exit...\n"); return -1; } fprintf(fp,"%s\n",buff);//将用户名写入到name.txt中 while(1) { //将select()监视的读,写,异常文件描述符清除 FD_ZERO(&rfd_set); FD_ZERO(&wfd_set); FD_ZERO(&efd_set); //将标准输入文件描述符加到select()监视的读文件描述符集合中 FD_SET(STDIN,&rfd_set); //添加新建的描述符加到select()监视的文件描述符中 FD_SET(client_fd,&rfd_set); FD_SET(client_fd,&wfd_set); FD_SET(client_fd,&efd_set); //设置select在被监视窗口等待的时间 timeout.tv_sec = 10; //秒 timeout.tv_usec = 0; //微妙 ret = select(client_fd+1,&rfd_set,&wfd_set,&efd_set,&timeout); if(ret==0) continue; if(ret<0) { perror("select error!"); exit(-1); } //判断是否已将标准输入文件描述符加到select()监视的读的文件描述符集合中 if(FD_ISSET(STDIN,&rfd_set)) { fgets(send_str,256,stdin);//读取键盘输入的内容 send_str[strlen(send_str)-1] = '\0'; if(strncmp("quit",send_str,4)==0) { close(client_fd); close(sockfd); exit(0); } send(client_fd,send_str,strlen(send_str),0); } //判断是否已将新建的描述符加到select()监视的读的文件描述符集合中 if(FD_ISSET(client_fd,&rfd_set)) { recvbytes = recv(client_fd,buf,MAXDATASIZE,0); if(recvbytes==0) { close(client_fd); close(sockfd); exit(0); } buf[recvbytes] = '\0'; printf("%s: %s\n",buff,buf); printf("Server: "); fflush(stdout); } //异常 if(FD_ISSET(client_fd,&efd_set)) { close(client_fd); exit(0); } }}
makefile
all: client serv.PHONY:all# make client:client : client_chat.o gcc -o client client_chat.oclient_chat.o : client_chat.c gcc -c client_chat.c# make serv:serv : server_chat.o gcc -o serv server_chat.oserver_chat.o : server_chat.c gcc -c server_chat.c# make clean:clean : rm -rf *.o client rm -rf *.o serv
阅读全文
0 0
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- Linux文件前面加点例如.bashrc表示什么意思
- H5 CSS基础二:清除浮动是个难点
- vue-cli for循环
- EventBus 源码试读(一)
- Scala控制结构
- 文章标题
- 判断某一年是否是闰年
- linux device tree 详解
- HDU-4291 A Short problem(矩阵快速幂)
- 虚拟机的桥接模式,NAT,仅主机三种网络模式
- Hacker(一)
- spring单例模式与线程安全问题的解决方案
- LightOJ 1422 Halloween Costumes
- Django 的request 和 response对象