很久没更新了,今天写了一个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;
}
不明白的地方请留言