1. 程式人生 > >Linux-聊天 socket程式設計

Linux-聊天 socket程式設計

1對1聊天

    通過select新增可讀事件的監聽實現。

    服務端:

#include "header.h"

int main(void)
{
	int listenfd = -1;
	int connfd = -1;
	struct sockaddr_in server, client;
	int on = 1;

	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(8888);
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if (0 > (listenfd = socket(AF_INET, SOCK_STREAM, 0)))
		err_exit("socket");

	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	if (0 > bind(listenfd, (struct sockaddr *)&server, sizeof(server)))
		err_exit("bind");
	
	listen(listenfd, 1024);
	printf("listen...\n");

	memset(&client, 0, sizeof(client));
	socklen_t len = sizeof(client);
	if (0 > (connfd = accept(listenfd, (struct sockaddr *)&client, &len)))
		err_exit("accept");
	printf("client's ip is:%s, port is:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

	char recv_buf[BUFSIZ];
	char send_buf[BUFSIZ];
	fd_set readfds;
	int maxfd = -1;
	int ret=-1;
	int i;
	
	while(1) {
		FD_ZERO(&readfds);//所有位置零

		FD_SET(0, &readfds);//設定0位元位為1,用於傳送資料訊息通知
		maxfd = maxfd > 0 ? maxfd : 0;
		FD_SET(connfd, &readfds);//設定connfd位元位為1,用於接受資料訊息通知,
		maxfd = maxfd > connfd ? maxfd : connfd;

		if (0 > select(maxfd + 1, &readfds, NULL, NULL, NULL))//設定被監聽的檔案描述符的總數為maxfd + 1,readfds可讀事件,且無限等待
			err_exit("select");

		for (i=0; i<=maxfd; i++) 
		{
			if (FD_ISSET(i, &readfds)) //select返回後,用FD_ISSET測試給定位是否置位,通過獲取那個bit位就知道是那個連線有資料
			{
				if (i == 0)//有資料需要傳送
				{
					fgets(send_buf, sizeof(send_buf), stdin);
					if (0 > send(connfd, send_buf, strlen(send_buf) + 1, 0))
						err_exit("send");				
				} 				
				else if (i == connfd)//有資料需要接收
				{
					if (0 > (ret = recv(connfd, recv_buf, BUFSIZ, 0)))
						err_exit("recv");
					else if (0 == ret) 
					{
						printf("client quit!\n");
						exit(0);
					}
					recv_buf[ret] = '\0';
					printf("client: %s\n", recv_buf);				
				}
			}
		}
	}

	close(listenfd);
	close(connfd);
	exit(0);
}

    客戶端:

#include "header.h"

int main(void)
{
	int connfd = -1;
	struct sockaddr_in server;
	
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(8888);
	server.sin_addr.s_addr = inet_addr("192.168.1.50");

	if (0 > (connfd = socket(AF_INET, SOCK_STREAM, 0)))
		err_exit("socket");

	if (0 > connect(connfd, (struct sockaddr *)&server, sizeof(server)))
		err_exit("connect");
	printf("connect success!\n");
	
	char send_buf[BUFSIZ];
	char recv_buf[BUFSIZ];
	int maxfd= -1;
	fd_set readfds;
	int ret=-1;
	int i;
	
	while(1) {
		FD_ZERO(&readfds);

		FD_SET(0, &readfds);
		maxfd = maxfd > 0 ? maxfd : 0;
		FD_SET(connfd, &readfds);
		maxfd = maxfd > connfd ? maxfd : connfd;
		
		if (0 > select(maxfd + 1, &readfds, NULL, NULL, NULL))
			err_exit("select");

		for (i=0; i<=maxfd; i++) 
		{
			if (FD_ISSET(i, &readfds)) 
			{
				if (0 == i) 
				{
					fgets(send_buf, sizeof(send_buf), stdin);		
					if (0 > send(connfd, send_buf, strlen(send_buf) + 1, 0))
						err_exit("send");				
				} 
				else if (connfd == i) 
				{
					if (0 > (ret = recv(connfd, recv_buf, BUFSIZ, 0)))
						err_exit("recv");
					else if (0 == ret) 
					{
						printf("server quit!\n");
						exit(0);
					}
					
					recv_buf[ret] = '\0';
					printf("server: %s\n", recv_buf);
				}
			}
		}
	}
	close(connfd);
	exit(0);
}

1對多聊天

select-多路複用通訊