socket編程基於IO複用的多客戶端服務器

很久沒更新了,今天寫了一個windows下的 socket編程基於IO複用的多客戶端服務器 , 重點在於select 函數,自行百度就可以了。
Talk is cheap , show me the code.

server.c
#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>
#define BUFSIZ 10
#pragma comment(lib,"ws2_32.lib")
void ErrorHandling(char * msg){
	puts(msg);
	system("pause");
	exit(1);
}
int main(){
	WSADATA wsd;
	SOCKET hServSock, hClntSock;
	SOCKADDR_IN servAdr, clntAdr;
	TIMEVAL timeout;
	fd_set reads, cpyReads;

	int adrSz;
	int strLen, fdNum;
	unsigned int i;
	char buf[BUFSIZ];

	//初始化socket庫
	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0){
		ErrorHandling("WSAStartup error!");
	}
	hServSock = socket(PF_INET,SOCK_STREAM,0);
	memset(&servAdr, 0, sizeof(servAdr));
	servAdr.sin_family = AF_INET;
	servAdr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	servAdr.sin_port = htons(6000);

	if (bind(hServSock,(SOCKADDR *)&servAdr,sizeof(SOCKADDR))==SOCKET_ERROR){
		ErrorHandling("bind() error");
	}
	if (listen(hServSock,5)==SOCKET_ERROR){
		ErrorHandling("listen() error");
	}
	hClntSock = socket(PF_INET, SOCK_STREAM, 0);
	FD_ZERO(&reads);
	FD_SET(hServSock, &reads);
	/*
	FD_SET(hClntSock, &reads);
	printf("%d",reads.fd_count);
	for (i = 0; i < reads.fd_count;i++){
		printf("%d",reads.fd_array[i]);
	}
	*/

	while (1){
		cpyReads = reads;
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;
		fdNum = select(0, &cpyReads, 0, 0, &timeout);
		if (fdNum==SOCKET_ERROR){
			break;
		}
		if (fdNum==0){
			continue;
		}
		for (i = 0; i<reads.fd_count;i++){
			if (FD_ISSET(reads.fd_array[i], &cpyReads)){
				if (reads.fd_array[i] == hServSock){
					adrSz = sizeof(clntAdr);
					hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &adrSz);
					FD_SET(hClntSock, &reads);
					printf("connected client: %d \n", hClntSock);
				} 
				else{
				//	memset(buf, 0, BUFSIZ);
					do{
						memset(buf, 0, BUFSIZ);
						strLen = recv(reads.fd_array[i], buf, BUFSIZ - 1, 0);
						if (strLen == 0 || strLen == -1){
							FD_CLR(reads.fd_array[i], &reads);
							closesocket(cpyReads.fd_array[i]);
							printf("closed client:%d \n", cpyReads.fd_array[i]);
						}
						else{
							printf("From %d : %s", cpyReads.fd_array[i], buf);
							//send(reads.fd_array[i], buf, strLen, 0);
						}
					} while (strLen==BUFSIZ-1);
					;
					/*if (strLen == 0 || strLen ==-1){
						FD_CLR(reads.fd_array[i], &reads);
						closesocket(cpyReads.fd_array[i]);
						printf("closed client:%d \n", cpyReads.fd_array[i]);
					}
					else{
						printf("From %d : %s",cpyReads.fd_array[i],buf);
						send(reads.fd_array[i], buf, strLen, 0);
					}*/
				}
			}
		}
		
	}
	closesocket(hServSock);
	WSACleanup();
	return 0;
}

client.c  (這裏的客戶端和之前的一樣,沒有改變)
#include<stdlib.h>
#include<stdio.h>
#include<WinSock2.h>

#pragma comment(lib,"ws2_32.lib")
void ErrorHandling(char * msg){
	puts(msg);
	system("pause");
	exit(1);
}

int main(){
	WSADATA wsd;
	SOCKET  sClient;
	SOCKADDR_IN addrClient;
	int sizeAddrClient = 0;
	int recvCount = 100;
	char charBuf[1024] = {0};
	//初始化socket庫
	if (WSAStartup(MAKEWORD(2, 2), &wsd)!=0){
		ErrorHandling("WSAStartup error!");
	}
	puts("初始化socket庫");

	//創建客戶端socket
	sClient = socket(AF_INET, SOCK_STREAM, 0);
	if (sClient==INVALID_SOCKET){
		ErrorHandling("socket() error!");
	}
	puts("創建客戶端socket");

	//初始化網絡地址信息
	memset(&addrClient, 0, sizeof(addrClient));
	addrClient.sin_family = AF_INET;
	addrClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addrClient.sin_port = htons(6000);
	puts("初始化網絡地址信息");

	//連接服務端
	if (connect(sClient,(SOCKADDR*)&addrClient,sizeof(addrClient))==SOCKET_ERROR){
		ErrorHandling("connect error!");
	}
	puts("現在可以向服務端發送消息");
	//循環發送消息(我規定最多爲200次)
	while (recvCount>0){
		memset(charBuf, 0, 1024);
		printf("To:");
		gets(charBuf);
		send(sClient, charBuf, strlen(charBuf), 0);
		memset(charBuf, 0, 1024);
		recvCount--;
	}
	//關閉socket
	closesocket(sClient);
	WSACleanup();
	puts("關閉socket");
	system("pause");
	return 0;
}
不明白的地方請留言


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章