服务器端:
建立socket,本地地址绑定bind,然后建立监听,如果有客户端请求则响应之,然后进行数据的发送和接收
源代码:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/time.h> #include <string.h> #include <fcntl.h> #define MAXDATASIZE 100 #define SERVPORT 3333 #define BACKLOG 10//最大连接数 #define STDIN 0 //标准输入 int main(void) { FILE *fp; int sockfd,client_fd;//socket.sock_fd监听,socket.new_fd数据传输 int sin_size; struct sockaddr_in my_addr,remote_addr;//本机地址信息,客户地址信息 char buf[256]; //用于聊天的缓冲区 char buff[256];//用于输入用户名的缓冲区 char send_str[256]; int recvbytes; fd_set rfd_set,wfd_set,efd_set;//被select监视的读,写,异常处理的文件描述符集合 struct timeval timeout; int ret; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socket"); exit(1); } /*端填充sockaddr结构*/ bzero(&my_addr,sizeof(struct sockaddr_in)); my_addr.sin_family=AF_INET;//地址族 my_addr.sin_port=htons(SERVPORT); inet_aton("127.0.0.1",&my_addr.sin_addr); if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1) { perror("bind"); exit(1); } if(listen(sockfd,BACKLOG)==-1) { perror("listen"); exit(1); } sin_size=sizeof(struct sockaddr_in); if((client_fd=accept(sockfd,(struct sockaddr *)&remote_addr,&sin_size))==-1) { perror("accept"); exit(1); } 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("can not open filie,exit.../n"); return -1; } fprintf(fp,"%s/n",buff); /*将用户名写入name.txt中*/ while(1) { FD_ZERO(&rfd_set);//读文件描述符清0 FD_ZERO(&wfd_set); FD_ZERO(&efd_set); 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); } 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); } } }
客户端:
先建立socket,然后请求连接(这里本机同为服务器和客户端,故均用回环地址),再进行数据的发送和接收
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <string.h> #include <fcntl.h> #define MAXDATASIZE 100 #define SERVPORT 3333 #define STDIN 0 //标准输入描述符 int main(void) { int sockfd;//套接字描述符 int recvbytes; char buf[MAXDATASIZE]; char *str; char name[MAXDATASIZE]; char send_str[MAXDATASIZE]; struct sockaddr_in serv_addr; fd_set rfd_set,wfd_set,efd_set; struct timeval timeout; int ret; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socket"); exit(1); } bzero(&serv_addr,sizeof(struct sockaddr_in)); serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(SERVPORT); inet_aton("127.0.0.1",&serv_addr.sin_addr); if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1) { perror("connect"); exit(1); } 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) { FD_ZERO(&rfd_set); FD_ZERO(&wfd_set); FD_ZERO(&efd_set); FD_SET(STDIN,&rfd_set); FD_SET(sockfd,&rfd_set); FD_SET(sockfd,&efd_set); 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); } /*判断是否已将新建的描述符加到select监听的异常的文件描述符集合中*/ if(FD_ISSET(sockfd,&efd_set)) { close(sockfd); exit(0); } } }