很久沒更新了,今天寫了一個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;
}
不明白的地方請留言