(1) 掌握Windows下异步通知I/O模型编程方法;
(2) 掌握Windows下重叠I/O模型编程方法;
(3) 掌握Windows下完成端口模型编程方法;
(1) 使用异步通知I/O模型实现回声服务器端(及客户端);
(2) 使用异步通知I/O模型编写聊天服务器端(及客户端);
(3) 使用重叠I/O模型实现回声服务器端(及客户端);
(4) 使用重叠I/O模型编写聊天服务器端(及客户端);
(5) 使用完成端口模型实现回声服务器端(及客户端);
(6) 使用完成端口模型编写聊天服务器端(及客户端)。
1.352页异步通知Io模型实现回声服务器
实验代码:
Server.c:
#include
#include
#include
#define BUF_SIZE 100
void CompressSockets(SOCKET hSockArr[], int idx, int total);
void CompressEvents(WSAEVENT hEventArr[], int idx, int total);
void ErrorHandling(char* msg);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN servAdr, clntAdr;
SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT newEvent;
WSANETWORKEVENTS netEvents;
int numOfClntSock = 0;
int strLen, i;
int posInfo, startIdx;
int clntAdrLen;
char msg[BUF_SIZE];
if (argc != 2) {
printf("Usage: %s \n" , argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 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_addr = htonl(INADDR_ANY);
servAdr.sin_port = htons(atoi(argv[1]));
if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error");
if (listen(hServSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() error");
newEvent = WSACreateEvent();
if (WSAEventSelect(hServSock, newEvent, FD_ACCEPT) == SOCKET_ERROR)
ErrorHandling("WSAEventSelect() error");
hSockArr[numOfClntSock] = hServSock;
hEventArr[numOfClntSock] = newEvent;
numOfClntSock++;
while (1)
{
posInfo = WSAWaitForMultipleEvents(
numOfClntSock, hEventArr, FALSE, WSA_INFINITE, FALSE);
startIdx = posInfo - WSA_WAIT_EVENT_0;
for (i = startIdx; i < numOfClntSock; i++)
{
int sigEventIdx =
WSAWaitForMultipleEvents(1, &hEventArr[i], TRUE, 0, FALSE);
if ((sigEventIdx == WSA_WAIT_FAILED || sigEventIdx == WSA_WAIT_TIMEOUT))
{
continue;
}
else
{
sigEventIdx = i;
WSAEnumNetworkEvents(
hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
if (netEvents.lNetworkEvents & FD_ACCEPT)
{
if (netEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
puts("Accept Error");
break;
}
clntAdrLen = sizeof(clntAdr);
hClntSock = accept(
hSockArr[sigEventIdx], (SOCKADDR*)&clntAdr, &clntAdrLen);
newEvent = WSACreateEvent();
WSAEventSelect(hClntSock, newEvent, FD_READ | FD_CLOSE);
hEventArr[numOfClntSock] = newEvent;
hSockArr[numOfClntSock] = hClntSock;
numOfClntSock++;
puts("connected new client...");
}
if (netEvents.lNetworkEvents & FD_READ)
{
if (netEvents.iErrorCode[FD_READ_BIT] != 0)
{
puts("Read Error");
break;
}
strLen = recv(hSockArr[sigEventIdx], msg, sizeof(msg), 0);
send(hSockArr[sigEventIdx], msg, strLen, 0);
}
if (netEvents.lNetworkEvents & FD_CLOSE)
{
if (netEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
puts("Close Error");
break;
}
WSACloseEvent(hEventArr[sigEventIdx]);
closesocket(hSockArr[sigEventIdx]);
numOfClntSock--;
CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
}
}
}
}
WSACleanup();
return 0;
}
void CompressSockets(SOCKET hSockArr[], int idx, int total)
{
int i;
for (i = idx; i < total; i++)
hSockArr[i] = hSockArr[i + 1];
}
void CompressEvents(WSAEVENT hEventArr[], int idx, int total)
{
int i;
for (i = idx; i < total; i++)
hEventArr[i] = hEventArr[i + 1];
}
void ErrorHandling(char* msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
Client.c:
#include
#include
#include
#include
#define BUF_SIZE 1024
void ErrorHandling(char* message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSocket;
char message[BUF_SIZE];
int strLen;
SOCKADDR_IN servAdr;
if (argc != 3) {
printf("Usage : %s \n" , argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = inet_addr(argv[1]);
servAdr.sin_port = htons(atoi(argv[2]));
if (connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("connect() error!");
else
puts("Connected...........");
while (1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
break;
send(hSocket, message, strlen(message), 0);
strLen = recv(hSocket, message, BUF_SIZE - 1, 0);
message[strLen] = 0;
printf("Message from server: %s", message);
}
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
Server.c:
#include
#include
#include
#define BUF_SIZE 100
void SendMsg(SOCKET clntSocks[], int clntCnt, char* msg, int len);
void CompressSockets(SOCKET hSockArr[], int idx, int total);
void CompressEvents(WSAEVENT hEventArr[], int idx, int total);
void ErrorHandling(char* msg);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN servAdr, clntAdr;
SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT newEvent;
WSANETWORKEVENTS netEvents;
int numOfClntSock = 0;
int strLen, i;
int posInfo, startIdx;
int clntAdrLen;
char msg[BUF_SIZE];
if (argc != 2) {
printf("Usage: %s \n" , argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hServSock = socket(PF_INET, SOCK_STREAM, 0);
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
servAdr.sin_port = htons(atoi(argv[1]));
if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error");
if (listen(hServSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() error");
newEvent = WSACreateEvent();
if (WSAEventSelect(hServSock, newEvent, FD_ACCEPT) == SOCKET_ERROR)
ErrorHandling("WSAEventSelect() error");
hSockArr[numOfClntSock] = hServSock;
hEventArr[numOfClntSock] = newEvent;
numOfClntSock++;
while (1)
{
posInfo = WSAWaitForMultipleEvents(
numOfClntSock, hEventArr, FALSE, WSA_INFINITE, FALSE);
startIdx = posInfo - WSA_WAIT_EVENT_0;
for (i = startIdx; i < numOfClntSock; i++)
{
int sigEventIdx =
WSAWaitForMultipleEvents(1, &hEventArr[i], TRUE, 0, FALSE);
if ((sigEventIdx == WSA_WAIT_FAILED || sigEventIdx == WSA_WAIT_TIMEOUT))
{
continue;
}
else
{
sigEventIdx = i;
WSAEnumNetworkEvents(
hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
if (netEvents.lNetworkEvents & FD_ACCEPT)
{
clntAdrLen = sizeof(clntAdr);
hClntSock = accept(
hSockArr[sigEventIdx], (SOCKADDR*)&clntAdr, &clntAdrLen);
newEvent = WSACreateEvent();
WSAEventSelect(hClntSock, newEvent, FD_READ | FD_CLOSE);
hEventArr[numOfClntSock] = newEvent;
hSockArr[numOfClntSock] = hClntSock;
numOfClntSock++;
puts("connected new client...");
}
if (netEvents.lNetworkEvents & FD_READ)
{
strLen = recv(hSockArr[sigEventIdx], msg, sizeof(msg), 0);
SendMsg(hSockArr, numOfClntSock, msg, strLen);
}
if (netEvents.lNetworkEvents & FD_CLOSE)
{
WSACloseEvent(hEventArr[sigEventIdx]);
closesocket(hSockArr[sigEventIdx]);
numOfClntSock--;
CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
}
}
}
}
WSACleanup();
return 0;
}
void SendMsg(SOCKET clntSocks[], int clntCnt, char* msg, int len) // send to all
{
int i;
for (i = 0; i < clntCnt; i++)
send(clntSocks[i], msg, len, 0);
}
void CompressSockets(SOCKET hSockArr[], int idx, int total)
{
int i;
for (i = idx; i < total; i++)
hSockArr[i] = hSockArr[i + 1];
}
void CompressEvents(WSAEVENT hEventArr[], int idx, int total)
{
int i;
for (i = idx; i < total; i++)
hEventArr[i] = hEventArr[i + 1];
}
void ErrorHandling(char* msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
Client.c:
#include
#include
#include
#include
#include
#define BUF_SIZE 100
#define NAME_SIZE 20
unsigned WINAPI SendMsg(void* arg);
unsigned WINAPI RecvMsg(void* arg);
void ErrorHandling(char* msg);
char name[NAME_SIZE] = "[DEFAULT]";
char msg[BUF_SIZE];
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSock;
SOCKADDR_IN servAdr;
HANDLE hSndThread, hRcvThread;
if (argc != 4) {
printf("Usage : %s \n" , argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
sprintf(name, "[%s]", argv[3]);
hSock = socket(PF_INET, SOCK_STREAM, 0);
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = inet_addr(argv[1]);
servAdr.sin_port = htons(atoi(argv[2]));
if (connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("connect() error");
hSndThread =
(HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL);
hRcvThread =
(HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);
WaitForSingleObject(hSndThread, INFINITE);
WaitForSingleObject(hRcvThread, INFINITE);
closesocket(hSock);
WSACleanup();
return 0;
}
unsigned WINAPI SendMsg(void* arg) // send thread main
{
SOCKET hSock = *((SOCKET*)arg);
char nameMsg[NAME_SIZE + BUF_SIZE];
while (1)
{
fgets(msg, BUF_SIZE, stdin);
if (!strcmp(msg, "q\n") || !strcmp(msg, "Q\n"))
{
closesocket(hSock);
exit(0);
}
sprintf(nameMsg, "%s %s", name, msg);
send(hSock, nameMsg, strlen(nameMsg), 0);
}
return 0;
}
unsigned WINAPI RecvMsg(void* arg) // read thread main
{
int hSock = *((SOCKET*)arg);
char nameMsg[NAME_SIZE + BUF_SIZE];
int strLen;
while (1)
{
strLen = recv(hSock, nameMsg, NAME_SIZE + BUF_SIZE - 1, 0);
if (strLen == -1)
return -1;
nameMsg[strLen] = 0;
fputs(nameMsg, stdout);
}
return 0;
}
void ErrorHandling(char* msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#define BUF_SIZE 1024
void CALLBACK ReadCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
void CALLBACK WriteCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
void ErrorHandling(char *message);
typedef struct
{
SOCKET hClntSock;
char buf[BUF_SIZE];
WSABUF wsaBuf;
} PER_IO_DATA, *LPPER_IO_DATA;
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hLisnSock, hRecvSock;
SOCKADDR_IN lisnAdr, recvAdr;
LPWSAOVERLAPPED lpOvLp;
DWORD recvBytes;
LPPER_IO_DATA hbInfo;
int mode=1, recvAdrSz, flagInfo=0;
if(argc!=2) {
printf("Usage: %s \n" , argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hLisnSock=WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
ioctlsocket(hLisnSock, FIONBIO, &mode); // for non-blocking socket
memset(&lisnAdr, 0, sizeof(lisnAdr));
lisnAdr.sin_family=AF_INET;
lisnAdr.sin_addr.s_addr=htonl(INADDR_ANY);
lisnAdr.sin_port=htons(atoi(argv[1]));
if(bind(hLisnSock, (SOCKADDR*) &lisnAdr, sizeof(lisnAdr))==SOCKET_ERROR)
ErrorHandling("bind() error");
if(listen(hLisnSock, 5)==SOCKET_ERROR)
ErrorHandling("listen() error");
recvAdrSz=sizeof(recvAdr);
while(1)
{
SleepEx(100, TRUE); // for alertable wait state
hRecvSock=accept(hLisnSock, (SOCKADDR*)&recvAdr,&recvAdrSz);
if(hRecvSock==INVALID_SOCKET)
{
if(WSAGetLastError()==WSAEWOULDBLOCK)
continue;
else
ErrorHandling("accept() error");
}
puts("Client connected.....");
lpOvLp=(LPWSAOVERLAPPED)malloc(sizeof(WSAOVERLAPPED));
memset(lpOvLp, 0, sizeof(WSAOVERLAPPED));
hbInfo=(LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
hbInfo->hClntSock=(DWORD)hRecvSock;
(hbInfo->wsaBuf).buf=hbInfo->buf;
(hbInfo->wsaBuf).len=BUF_SIZE;
lpOvLp->hEvent=(HANDLE)hbInfo;
WSARecv(hRecvSock, &(hbInfo->wsaBuf),
1, &recvBytes, &flagInfo, lpOvLp, ReadCompRoutine);
}
closesocket(hRecvSock);
closesocket(hLisnSock);
WSACleanup();
return 0;
}
void CALLBACK ReadCompRoutine(
DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo=(LPPER_IO_DATA)(lpOverlapped->hEvent);
SOCKET hSock=hbInfo->hClntSock;
LPWSABUF bufInfo=&(hbInfo->wsaBuf);
DWORD sentBytes;
if(szRecvBytes==0)
{
closesocket(hSock);
free(lpOverlapped->hEvent); free(lpOverlapped);
puts("Client disconnected.....");
}
else // echo!
{
bufInfo->len=szRecvBytes;
WSASend(hSock, bufInfo, 1, &sentBytes, 0, lpOverlapped, WriteCompRoutine);
}
}
void CALLBACK WriteCompRoutine(DWORD dwError, DWORD szSendBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo=(LPPER_IO_DATA)(lpOverlapped->hEvent);
SOCKET hSock=hbInfo->hClntSock;
LPWSABUF bufInfo=&(hbInfo->wsaBuf);
DWORD recvBytes;
int flagInfo=0;
WSARecv(hSock, bufInfo, 1, &recvBytes, &flagInfo, lpOverlapped, ReadCompRoutine);
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#define BUF_SIZE 1024
void ErrorHandling(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAdr;
char message[BUF_SIZE];
int strLen, readLen;
if(argc!=3) {
printf("Usage: %s \n" , argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
ErrorHandling("WSAStartup() error!");
hSocket=socket(PF_INET, SOCK_STREAM, 0);
if(hSocket==INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=inet_addr(argv[1]);
servAdr.sin_port=htons(atoi(argv[2]));
if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR)
ErrorHandling("connect() error!");
else
puts("Connected...........");
while(1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
break;
strLen=strlen(message);
send(hSocket, message, strLen, 0);
readLen=0;
while(1)
{
readLen+=recv(hSocket, &message[readLen], BUF_SIZE-1, 0);
if(readLen>=strLen)
break;
}
message[strLen]=0;
printf("Message from server: %s", message);
}
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
Server:
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
#define BUF_SIZE 1024
void CALLBACK ReadCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
void CALLBACK WriteCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD);
void ErrorHandling(char *message);
typedef struct
{
SOCKET hClntSock;
char buf[BUF_SIZE];
WSABUF wsaBuf;
} PER_IO_DATA, *LPPER_IO_DATA;
SOCKET ALLCLIENT[100];//所有客户端
int CONNECNUM = 0;//计数
LPWSAOVERLAPPED overlap[100];//所有客户端的相关结构
int overcount = 0;
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hLisnSock, hRecvSock;
SOCKADDR_IN lisnAdr, recvAdr;
LPWSAOVERLAPPED lpOvLp;
DWORD recvBytes=0;
LPPER_IO_DATA hbInfo;
u_long mode = 1;
DWORD flagInfo = 0;
int recvAdrSz=0;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hLisnSock = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
ioctlsocket(hLisnSock, FIONBIO, &mode); // for non-blocking socket(非阻塞套接字)
memset(&lisnAdr, 0, sizeof(lisnAdr));
lisnAdr.sin_family = AF_INET;
lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY);
lisnAdr.sin_port = htons(1234);
if (bind(hLisnSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error");
if (listen(hLisnSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() error");
recvAdrSz = sizeof(recvAdr);
while (1)
{
SleepEx(100, TRUE); // for alertable wait state(设置状态)
hRecvSock = accept(hLisnSock, (SOCKADDR*)&recvAdr, &recvAdrSz);
if (hRecvSock == INVALID_SOCKET)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)//只表示无连接
continue;
else
ErrorHandling("accept() error");
}
ALLCLIENT[CONNECNUM++] = hRecvSock;
puts("Client connected.....");
lpOvLp = (LPWSAOVERLAPPED)malloc(sizeof(WSAOVERLAPPED));
overlap[overcount++] = lpOvLp;//存入数组
memset(lpOvLp, 0, sizeof(WSAOVERLAPPED));
hbInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
hbInfo->hClntSock = (DWORD)hRecvSock;
(hbInfo->wsaBuf).buf = hbInfo->buf;
(hbInfo->wsaBuf).len = BUF_SIZE;
lpOvLp->hEvent = (HANDLE)hbInfo;//特殊类型转换
if (
WSARecv(hRecvSock, &(hbInfo->wsaBuf),
1, &recvBytes, &flagInfo, lpOvLp, ReadCompRoutine)==SOCKET_ERROR)
if (WSAGetLastError() == WSA_IO_PENDING)
{
printf("接收数据中.");
}
}
closesocket(hRecvSock);
closesocket(hLisnSock);
WSACleanup();
return 0;
}
void CALLBACK ReadCompRoutine(//参数:(错误信息,实际收发字节数,WSA*的lpOverlapped参数,特性信息或0)
DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent);//类型转回
SOCKET hSock = hbInfo->hClntSock;
LPWSABUF bufInfo = &(hbInfo->wsaBuf);
DWORD sentBytes;
if (szRecvBytes == 0)
{
int i = 0;
while (ALLCLIENT[i] != hSock)i++;
ALLCLIENT[i] = -1;
closesocket(hSock);
free(lpOverlapped->hEvent); free(lpOverlapped);
puts("Client disconnected.....");
}
else // echo!
{
bufInfo->len = szRecvBytes;//存储实际接收到的字节数,在A发送一条,B发送一条,A再发送一条信息时接受到的信息会出错,不知道原因??
int k = 0;
for (; k < CONNECNUM; k++)
{
if (ALLCLIENT[k] != -1)
{
int result = 0;
result = WSASend(ALLCLIENT[k], bufInfo, 1, &sentBytes, 0, overlap[k], WriteCompRoutine);
}
}
}
}
void CALLBACK WriteCompRoutine(//参数:(错误信息,实际收发字节数,WSA*的lpOverlapped参数,特性信息或0)
DWORD dwError, DWORD szSendBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags)
{
LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent);
SOCKET hSock = hbInfo->hClntSock;
LPWSABUF bufInfo = &(hbInfo->wsaBuf);
DWORD recvBytes=0;
DWORD flagInfo = 0;
int result = WSARecv(hSock, bufInfo,
1, &recvBytes, &flagInfo, lpOverlapped, ReadCompRoutine);
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
Client:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#define BUF_SIZE 1000
#define NAME_SIZE 20
#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
unsigned WINAPI SendMsg(void * arg);//发送信息函数
unsigned WINAPI RecvMsg(void * arg);//接受信息函数
void ErrorHandling(char * msg);//错误返回函数
int haveread = 0;
char NAME[50];//[名字]
char ANAME[50];
char msg[BUF_SIZE];//信息
int main(int argc, char *argv[])
{
printf("请输入网名:");
scanf("%s", NAME);
WSADATA wsaData;
SOCKET hSock;
SOCKADDR_IN servAdr;
HANDLE hSndThread, hRcvThread;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hSock = socket(PF_INET, SOCK_STREAM, 0);
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = inet_addr("127.0.0.1");
servAdr.sin_port = htons(1234);
if (connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
ErrorHandling("connect() error");
int resultsend;
puts("Welcome to joining our chatting room!\n");
sprintf(ANAME, "[%s]", NAME);
hSndThread =
(HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL);//写线程
hRcvThread =
(HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);//读线程
WaitForSingleObject(hSndThread, INFINITE);//等待线程结束
WaitForSingleObject(hRcvThread, INFINITE);
closesocket(hSock);
WSACleanup();
system("pause");
return 0;
}
unsigned WINAPI SendMsg(void * arg) // send thread main
{
SOCKET sock = *((SOCKET*)arg);
char name_msg[NAME_SIZE + BUF_SIZE];
char padd[2];
fgets(padd, 2, stdin);//多余的'\n'
printf("\n send message:");
while (1)
{
{
fgets(msg, BUF_SIZE, stdin);
if (!strcmp(msg, "q\n") || !strcmp(msg, "Q\n"))
{
closesocket(sock);
exit(0);
}
sprintf(name_msg, "[%s] %s", NAME, msg);
char numofmsg = strlen(name_msg)+'0';
char newmsg[100]; newmsg[0] = numofmsg; newmsg[1] = 0;//第一个字符表示消息的长度
strcat(newmsg, name_msg);
printf("信息的长度:%d", strlen(newmsg));
int result = send(sock, newmsg, strlen(newmsg), 0);
printf("客户端发送的消息:%s\n", newmsg);
if (result == -1)return -1;//发送错误
}
}
return NULL;
}
unsigned WINAPI RecvMsg(void * arg) // read thread main
{
SOCKET sock = *((SOCKET*)arg);
char name_msg[NAME_SIZE + BUF_SIZE];
int str_len = 0;
while (1)
{
{
char lyfstr[1000] = { 0 };
int totalnum = 0;
str_len = recv(sock, name_msg, 1, 0);//读取第一个字符!获取消息的长度
name_msg[str_len] = 0;
strcat(lyfstr, name_msg);
if (str_len == -1)//读取错误
{
printf("return -1\n");
return -1;
}
if (str_len == 0)//读取结束
{
printf("return 0\n");
return 0;//读取结束
}
totalnum = name_msg[0]-'0';
int count = 0;
do
{
str_len = recv(sock, name_msg, 1, 0);
name_msg[str_len] = 0;
if (str_len == -1)//读取错误
{
printf("return -1\n");
return -1;
}
if (str_len == 0)
{
printf("return 0\n");
return 0;//读取结束
}
strcat(lyfstr, name_msg);
count = str_len+count;
} while (count < totalnum);
lyfstr[count] = '\0';
printf("\n");
strcat(lyfstr, "\n");
fputs(lyfstr, stdout);
printf(" send message:");
fflush(stdout);
memset(name_msg, 0, sizeof(char));
}
}
return NULL;
}
void ErrorHandling(char * msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#include
#include
#define BUF_SIZE 100
#define READ 3
#define WRITE 5
typedef struct // socket info
{
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
} PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
typedef struct // buffer info
{
OVERLAPPED overlapped;
WSABUF wsaBuf;
char buffer[BUF_SIZE];
int rwMode; // READ or WRITE
} PER_IO_DATA, *LPPER_IO_DATA;
DWORD WINAPI EchoThreadMain(LPVOID CompletionPortIO);
void ErrorHandling(char *message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
HANDLE hComPort;
SYSTEM_INFO sysInfo;
LPPER_IO_DATA ioInfo;
LPPER_HANDLE_DATA handleInfo;
SOCKET hServSock;
SOCKADDR_IN servAdr;
int recvBytes, i, flags=0;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hComPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
GetSystemInfo(&sysInfo);
for(i=0; i<sysInfo.dwNumberOfProcessors; i++)
_beginthreadex(NULL, 0, EchoThreadMain, (LPVOID)hComPort, 0, NULL);
hServSock=WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
servAdr.sin_port=htons(atoi(argv[1]));
bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr));
listen(hServSock, 5);
while(1)
{
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
int addrLen=sizeof(clntAdr);
hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr, &addrLen);
handleInfo=(LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
handleInfo->hClntSock=hClntSock;
memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen);
CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, 0);
ioInfo=(LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
ioInfo->wsaBuf.len=BUF_SIZE;
ioInfo->wsaBuf.buf=ioInfo->buffer;
ioInfo->rwMode=READ;
WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf),
1, &recvBytes, &flags, &(ioInfo->overlapped), NULL);
}
return 0;
}
DWORD WINAPI EchoThreadMain(LPVOID pComPort)
{
HANDLE hComPort=(HANDLE)pComPort;
SOCKET sock;
DWORD bytesTrans;
LPPER_HANDLE_DATA handleInfo;
LPPER_IO_DATA ioInfo;
DWORD flags=0;
while(1)
{
GetQueuedCompletionStatus(hComPort, &bytesTrans,
(LPDWORD)&handleInfo, (LPOVERLAPPED*)&ioInfo, INFINITE);
sock=handleInfo->hClntSock;
if(ioInfo->rwMode==READ)
{
puts("message received!");
if(bytesTrans==0)
{
closesocket(sock);
free(handleInfo); free(ioInfo);
continue;
}
memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
ioInfo->wsaBuf.len=bytesTrans;
ioInfo->rwMode=WRITE;
WSASend(sock, &(ioInfo->wsaBuf), 1, NULL, 0, &(ioInfo->overlapped), NULL);
ioInfo=(LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
ioInfo->wsaBuf.len=BUF_SIZE;
ioInfo->wsaBuf.buf=ioInfo->buffer;
ioInfo->rwMode=READ;
WSARecv(sock, &(ioInfo->wsaBuf), 1, NULL, &flags, &(ioInfo->overlapped), NULL);
}
else
{
puts("message sent!");
free(ioInfo);
}
}
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#define BUF_SIZE 1024
void ErrorHandling(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAdr;
char message[BUF_SIZE];
int strLen, readLen;
if(argc!=3) {
printf("Usage: %s \n" , argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
ErrorHandling("WSAStartup() error!");
hSocket=socket(PF_INET, SOCK_STREAM, 0);
if(hSocket==INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=inet_addr(argv[1]);
servAdr.sin_port=htons(atoi(argv[2]));
if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR)
ErrorHandling("connect() error!");
else
puts("Connected...........");
while(1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
break;
strLen=strlen(message);
send(hSocket, message, strLen, 0);
readLen=0;
while(1)
{
readLen+=recv(hSocket, &message[readLen], BUF_SIZE-1, 0);
if(readLen>=strLen)
break;
}
message[strLen]=0;
printf("Message from server: %s", message);
}
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#include
#include
#define BUF_SIZE 100
#define MAX_CLNT 256
#define READ 3
#define WRITE 5
typedef struct // socket info
{
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
} PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
typedef struct // buffer info
{
OVERLAPPED overlapped;
WSABUF wsaBuf;
char buffer[BUF_SIZE];
} PER_IO_DATA, *LPPER_IO_DATA;
DWORD WINAPI EchoThreadMain(LPVOID CompletionPortIO);
void SendMsg(char * msg, DWORD len);
void ErrorHandling(char *message);
int clntCnt=0;
SOCKET clntSocks[MAX_CLNT];
int main(int argc, char* argv[])
{
WSADATA wsaData;
HANDLE hComPort;
SYSTEM_INFO sysInfo;
LPPER_IO_DATA ioInfo;
LPPER_HANDLE_DATA handleInfo;
SOCKET hServSock;
SOCKADDR_IN servAdr;
int recvBytes, i, flags=0;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hComPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
GetSystemInfo(&sysInfo);
for(i=0; i<sysInfo.dwNumberOfProcessors; i++)
_beginthreadex(NULL, 0, EchoThreadMain, (LPVOID)hComPort, 0, NULL);
hServSock=WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
servAdr.sin_port=htons(atoi(argv[1]));
bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr));
listen(hServSock, 5);
while(1)
{
SOCKET hClntSock;
SOCKADDR_IN clntAdr;
int addrLen=sizeof(clntAdr);
hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr, &addrLen);
clntSocks[clntCnt++]=hClntSock;
handleInfo=(LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
handleInfo->hClntSock=hClntSock;
memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen);
CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, 0);
ioInfo=(LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
ioInfo->wsaBuf.len=BUF_SIZE;
ioInfo->wsaBuf.buf=ioInfo->buffer;
WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf),
1, &recvBytes, &flags, &(ioInfo->overlapped), NULL);
}
return 0;
}
DWORD WINAPI EchoThreadMain(LPVOID pComPort)
{
HANDLE hComPort=(HANDLE)pComPort;
SOCKET sock;
DWORD bytesTrans;
LPPER_HANDLE_DATA handleInfo;
LPPER_IO_DATA ioInfo;
DWORD flags=0;
int i;
while(1)
{
GetQueuedCompletionStatus(hComPort, &bytesTrans,
(LPDWORD)&handleInfo, (LPOVERLAPPED*)&ioInfo, INFINITE);
sock=handleInfo->hClntSock;
puts("message received!");
if(bytesTrans==0) // EOF
{
for(i=0; i<clntCnt; i++) // remove disconnected client
{
if(sock==clntSocks[i])
{
while(i++<clntCnt-1)
clntSocks[i]=clntSocks[i+1];
break;
}
}
clntCnt--;
closesocket(sock);
free(handleInfo); free(ioInfo);
continue;
}
SendMsg(ioInfo->buffer, bytesTrans);
memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
WSARecv(sock, &(ioInfo->wsaBuf),
1, NULL, &flags, &(ioInfo->overlapped), NULL);
}
return 0;
}
void SendMsg(char * msg, DWORD len) // send to all
{
int i;
for(i=0; i<clntCnt; i++)
send(clntSocks[i], msg, len, 0);
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
#include
#include
#include
#include
#include
#define BUF_SIZE 100
#define NAME_SIZE 20
unsigned WINAPI SendMsg(void * arg);
unsigned WINAPI RecvMsg(void * arg);
void ErrorHandling(char * msg);
char name[NAME_SIZE]="[DEFAULT]";
char msg[BUF_SIZE];
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET hSock;
SOCKADDR_IN servAdr;
HANDLE hSndThread, hRcvThread;
if(argc!=4) {
printf("Usage : %s \n" , argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
ErrorHandling("WSAStartup() error!");
sprintf(name, "[%s]", argv[3]);
hSock=socket(PF_INET, SOCK_STREAM, 0);
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family=AF_INET;
servAdr.sin_addr.s_addr=inet_addr(argv[1]);
servAdr.sin_port=htons(atoi(argv[2]));
if(connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR)
ErrorHandling("connect() error");
hSndThread=
(HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL);
hRcvThread=
(HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);
WaitForSingleObject(hSndThread, INFINITE);
WaitForSingleObject(hRcvThread, INFINITE);
closesocket(hSock);
WSACleanup();
return 0;
}
unsigned WINAPI SendMsg(void * arg) // send thread main
{
SOCKET hSock=*((SOCKET*)arg);
char nameMsg[NAME_SIZE+BUF_SIZE];
while(1)
{
fgets(msg, BUF_SIZE, stdin);
if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n"))
{
closesocket(hSock);
exit(0);
}
sprintf(nameMsg,"%s %s", name, msg);
send(hSock, nameMsg, strlen(nameMsg), 0);
}
return 0;
}
unsigned WINAPI RecvMsg(void * arg) // read thread main
{
int hSock=*((SOCKET*)arg);
char nameMsg[NAME_SIZE+BUF_SIZE];
int strLen;
while(1)
{
strLen=recv(hSock, nameMsg, NAME_SIZE+BUF_SIZE-1, 0);
if(strLen==-1)
return -1;
nameMsg[strLen]=0;
fputs(nameMsg, stdout);
}
return 0;
}
void ErrorHandling(char *msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}