Linux socket网络编程之聊天室(三):select异步通讯实现

1.服务器端

/*select_server.c 2011.9.2 by yyg*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>

#define MAXBUF 1024

int main(int argc,char **argv){
	int sockfd,new_fd;
	socklen_t len;
	struct sockaddr_in my_addr,their_addr;
	unsigned int myport,lisnum;
	char buf[MAXBUF+1];
	fd_set rfds;
	struct timeval tv;
	int retval,maxfd = -1;

	if(argv[1]){
		myport = atoi(argv[1]);
	}
	else
		myport = 7838;

	if(argv[2]){
		lisnum = atoi(argv[2]);
	}
	else
		lisnum =2;
	if((sockfd = socket(PF_INET,SOCK_STREAM,0))== -1){
		perror("socket");
		exit(1);
	}

	bzero(&my_addr,sizeof(my_addr));
	my_addr.sin_family = PF_INET;
	my_addr.sin_port = htons(myport);
	if(argv[3])
		my_addr.sin_addr.s_addr = INADDR_ANY;
	
	if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1){
		perror("bind");
		exit(1);
	}
	
	if(listen(sockfd, lisnum) == -1){
		perror("listen");
		exit(1);
	}
	
	while(1){
		printf("\n----waiting for new connecting to start new char----\n");
		len = sizeof(struct sockaddr);
		if((new_fd = accept(sockfd,(struct sockaddr *)&their_addr,&len)) == -1){
			perror("accept");
			exit(errno);
		}
		else
			printf("server:got connection from %s,port %d,socked %d\n",\
				inet_ntoa(their_addr.sin_addr),\
				ntohs(their_addr.sin_port),new_fd);
		
		/*开始处理每个新连接上的数据收发*/
		//printf("\n---ready to go.now you can chatting...input enter,then you can chat---\n");
		while(1){
			/*把集合清空*/
			FD_ZERO(&rfds);
			/*把标准输入句柄0加入到集合中*/
			FD_SET(0,&rfds);
			maxfd = 0;
			/*把当前连接句柄new_fd加入到集合中*/
			FD_SET(new_fd,&rfds);
			if(new_fd > maxfd)
				maxfd = new_fd;
			/*设置最大等待时间*/
			tv.tv_sec = 1;
			tv.tv_usec = 0;

			retval = select(maxfd+1,&rfds,NULL,NULL,&tv);
			if(retval == -1){
				printf("select error!%s\n",strerror(errno));
				break;
			}
			else if(retval == 0){
				//printf("no message come,user no press the button,please wait...\n");
				continue;
			}
			else{

				if(FD_ISSET(new_fd,&rfds)){
				/*连接的socket 上有消息则接收并显示*/
					bzero(buf,MAXBUF+1);
					/*接收对方发过来的消息,最多MAXBUF字节*/
					len = recv(new_fd, buf, MAXBUF, 0);
					if(len > 0)
						printf("recv msg success:%s! %d bytes rcv.\n ",buf,len);
					else{
						if(len < 0){
							printf("recv msg fail.the errno is:%d,error info is %s.\n",errno,strerror(errno));
						}
						else
							printf("quit.\n");
						break;
					}
				}// FD_ISSET = sockfd情况
				if(FD_ISSET(0,&rfds)){
					/*用户有输入了,则读取其内容并发送*/
					bzero(buf, MAXBUF+1);
					fgets(buf, MAXBUF, stdin);
					if(!strncasecmp(buf, "quit", 4)){
						printf("self request to quit the chating\n");
						break;
					}
					/*发消息给服务器*/
					len = send(new_fd, buf, strlen(buf)-1 , 0);
					if(len < 0){
						printf("mgs:%s send fail!errno is:%d,error info is:%s\n", buf, errno, strerror(errno));
						break;
					}else{
						printf("msg: %s\t send success, send %d bytes!\n", buf, len);
					}
				}//FD_ISSET = 0
			
			}//select 处理结束
			
		}/*内while*/
		close(new_fd);
		/*处理每个新连接上的数据收发结束*/
		printf("would you want to chatting with another one?(no->quit)");
		fflush(stdout);
		bzero(buf,MAXBUF+1);
		fgets(buf,MAXBUF,stdin);
		if(!strncasecmp(buf,"no",2)){
			printf("quit the chatting!\n");
			break;
		}
	
	}/*外while*/

	close(sockfd);
	return 0;
}

2.客户端

/*select_client.c 2011.9.2 by yyg*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <resolv.h>

#define MAXBUF 1024
int main(int argc,char **argv){
	int sockfd,len;
	struct sockaddr_in dest;
	char buffer[MAXBUF+1];
	fd_set rfds;
	struct timeval tv;
	int retval,maxfd = -1;

	if(argc != 3){
		printf("the param style wrong!\n");
		exit(0);
	}
	/*创建一个socket用于tcp通信*/
	if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0){
		perror("socket");
		exit(errno);
	}

	/*初始化服务器端(对方)的地址和端口信息*/
	bzero(&dest,sizeof(dest));
	dest.sin_family = AF_INET;
	dest.sin_port = htons(atoi(argv[2]));
	if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr) == 0){
		perror(argv[1]);
		exit(errno);
	}

	/*conect to the server*/
	if(connect(sockfd,(struct sockaddr*)&dest,sizeof(dest)) !=0){
		perror("connect");
		exit(errno);
	}

	printf("\n---ready to chatting...---\n");
	while(1){
		/*把集合清空*/
		FD_ZERO(&rfds);
		/*把标准输入句柄0加入到集合中*/
		FD_SET(0,&rfds);
		maxfd = 0;
		/*把当前连接句柄socket 加入到集合中*/
		FD_SET(sockfd,&rfds);
		if(sockfd > maxfd)
			maxfd = sockfd;
		/*设置最大等待时间*/
		tv.tv_sec = 1;
		tv.tv_usec = 0;
		/*开始等待*/
		retval = select(maxfd+1,&rfds,NULL,NULL,&tv);
		if(retval == -1){
			printf("select error,quit!\n");
			break;
		}else if(retval == 0){
			continue;
		}else{
			if(FD_ISSET(sockfd,&rfds)){
				/*连接的socket 上有消息则接收并显示*/
				bzero(buffer,MAXBUF+1);
				/*接收对方发过来的消息,最多MAXBUF字节*/
				len = recv(sockfd, buffer, MAXBUF, 0);
				if(len > 0)
					printf("recv msg success:%s! %d bytes rcv.\n ",buffer,len);
				else{
					if(len < 0){
						printf("recv msg fail.the errno is:%d,error info is %s.\n",errno,strerror(errno));
					}
					else
						printf("quit.\n");
					break;
				}
			}// FD_ISSET = sockfd情况
			if(FD_ISSET(0,&rfds)){
				/*用户有输入了,则读取其内容并发送*/
				bzero(buffer, MAXBUF+1);
				fgets(buffer, MAXBUF, stdin);
				if(!strncasecmp(buffer, "quit", 4)){
					printf("self request to quit the chating\n");
					break;
				}
				/*发消息给服务器*/
				len = send(sockfd, buffer, strlen(buffer)-1 , 0);
				if(len < 0){
					printf("mgs:%s send fail!errno is:%d,error info is:%s\n", buffer, errno, strerror(errno));
					break;
				}else{
					printf("msg: %s\t send success, send %d bytes!\n", buffer, len);
				}
			}//FD_ISSET = 0
			
		}//select 处理结束

	}//处理聊天的while 循环
	/*关闭连接*/
	close(sockfd);
	return 0;
}

运行结果:

终端1:服务器端

[root@localhost net]# ./select_server 7838

----waiting for new connecting to start new char----
server:got connection from 172.31.100.236,port 59462,socked 4
recv msg success:kfldsjfk! 8 bytes rcv.
456354
 msg: 456354
         send success, send 6 bytes!
recv msg success:453455! 6 bytes rcv.

终端2:客户端

[root@localhost net]#  ./select_client 172.31.100.236 7838

---ready to chatting...---
kfldsjfk
msg: kfldsjfk
         send success, send 8 bytes!
recv msg success:456354! 6 bytes rcv.
453455
 msg: 453455
         send success, send 6 bytes!





2.客户端

你可能感兴趣的:(编程,linux,socket,网络,聊天,通讯)