1.包含以下内容
#define WIN32_LEAN_AND_MEAN //定义宏,不会出现error C2011: 'fd_set' : 'struct' type redefinition等错误
#define VC_EXTRALEAN
#include <windows.h>
#include <winsock2.h>
#include "iostream"
#pragma comment(lib, "Ws2_32.lib")
2.定义结构体
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND; //发送字节数
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
3.初始化socket
WORD wVersionRequested;
WSADATA wsaData;
int Ret;
wVersionRequested = MAKEWORD(2,0);
//err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return;
}
4.申请PER_IO_DATA
//使用NEW不可以。
//PerHandleData = new PER_HANDLE_DATA;
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
5.一个例子
//server.cpp
#include <winsock2.h>
#include <windows.h>
#include "socketapi.h"
#include "socketnotify.h"
#include "iostream"
using namespace std;
#pragma comment(lib, "Ws2_32")
#define OP_READ 0
#define OP_WRITE 1
#define OP_ACCEPT 2
#define DATA_BUFSIZE 1024
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND; //发送字节数
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
DWORD __stdcall CompletionRoutine(LPVOID Param);
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int Ret;
wVersionRequested = MAKEWORD(2,0);
//err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d\n", Ret);
return;
}
HANDLE CompletionPort;
LPPER_HANDLE_DATA PerHandleData ;
LPPER_IO_OPERATION_DATA PerIoData ;
SOCKADDR_IN InternetAddr;
DWORD RecvBytes;
DWORD Flags;
SOCKET server;
SOCKET Accept;
if ((server = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(8000);
if (bind(server, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return;
}
if (listen(server, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
WSACleanup();
return;
}
// server.set_port(8000);
// server.listen();
/**////////////////////////////
//取得系统中CPU的数目,创建和CPU数目相等的线程,如果事先估计到完成端口处理线程会堵塞,
//可以考虑创建 SysInfo.dwNumberOfProcessors*2个线程。一般在单处理器上创建和CPU数目相等
//的线程就可以了
//获得CPU个数
SYSTEM_INFO sysInfo;
ZeroMemory(&sysInfo,sizeof(SYSTEM_INFO));
ZeroMemory(&wsaData,sizeof(WSADATA));
GetSystemInfo(&sysInfo);
int nNumberOfConcurrent = sysInfo.dwNumberOfProcessors * 2+2;
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nNumberOfConcurrent);
if (NULL == CompletionPort)
{
cout << "CreateIoCompletionPort() failed: " << GetLastError() << endl;
return ;
}
PER_IO_OPERATION_DATA per_io_data;
cout<<"port:"<<CompletionPort<<endl;
HANDLE m_hThreadArray[8];
for (int i=0; i<1; i++)
{
m_hThreadArray[i] = CreateThread(NULL, 0, CompletionRoutine, (LPVOID)CompletionPort, 0, NULL);
if (NULL == m_hThreadArray[i])
{
while (i>0)
{
CloseHandle(m_hThreadArray[i-1]);
m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
i--;
}//end of while
cout << "CreateThread() failed: " << GetLastError() << endl;
CloseHandle(CompletionPort);
return ;
}
}//end of for
Sleep(1000);
while(1)
{
cout<<"waiting for accept "<<endl;
//int sClient = server.accept();
if ((Accept = WSAAccept(server, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
}
cout<<"accetp :"<<Accept<<endl;
//PerHandleData = new PER_HANDLE_DATA;
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
PerHandleData->Socket = Accept;
if(CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD)PerHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return ;
}
//PerIoData = new PER_IO_OPERATION_DATA;
//
//清管子的数据结构,准备往里面灌数据
//
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
memset(&(PerIoData->Overlapped), sizeof(OVERLAPPED),0);
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
//
// accept接到了数据,就放到PerIoData中,而perIoData又通过线程中的函数取出,
//
RecvBytes = 0;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("main WSARecv() failed with error %d\n", WSAGetLastError());
WSACleanup();
return;
}
}
//cout<<"recv :"<<PerIoData->Buffer<<endl;
}
PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL);
CloseHandle(CompletionPort);
WSACleanup();
cin>>i;
return ;
}
DWORD __stdcall CompletionRoutine(LPVOID Param)
{
HANDLE CompletionPort = (HANDLE) Param;
PER_IO_OPERATION_DATA *pData = (PER_IO_OPERATION_DATA*)Param;
DWORD BytesTransferred;
LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(1)
{
int bSuccess = GetQueuedCompletionStatus(
CompletionPort,
&BytesTransferred,
(LPDWORD)&PerHandleData,
(LPOVERLAPPED *) &PerIoData,
INFINITE
);
cout<<"----------------------------"<<endl;
if (0 == bSuccess)
{
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
int iError = WSAGetLastError();
if ( iError!= ERROR_IO_PENDING)
{
printf("client %d closed \n", PerHandleData->Socket);
closesocket(PerHandleData->Socket);
}
}
continue;
}
if (NULL == PerIoData)
{
//
cout<<"//PostQueuedCompletionStatus发过来一个空的单句柄数据,表示线程要退出了。"<<endl;
//
return 0;
}
Flags = 0;
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("thread WSARecv() failed with error %d\n", WSAGetLastError());
return 0;
}
}
cout<<"recv from "<<PerHandleData->Socket<<":"<<PerIoData->Buffer<<endl;
}
return 0;
}
#include "iostream"
#include <winsock2.h>
#include <windows.h>
using namespace std;
#pragma comment(lib, "Ws2_32")
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2,0);
err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
if(err != 0)
{
cout<<"socket init error."<< endl;
}
int i=0;
int iRet = 0;
SOCKET client;
client = socket( AF_INET, SOCK_STREAM, 0);
if( client == INVALID_SOCKET )
{
cout<< "socket() error"<<WSAGetLastError() <<endl;
}
SOCKADDR_IN saServer;
memset(&saServer,0,sizeof(saServer));
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = inet_addr("127.0.0.1");
saServer.sin_port = htons(8000);
int nRet = connect(client,(sockaddr*)&saServer, sizeof(saServer));
if( iRet == SOCKET_ERROR)
{
cout<<"connect error"<<endl;
return 0;
}
else
{
cout<<"iRet:"<<iRet<<endl;
cout<<"connect success"<<WSAGetLastError()<<endl;
}
char buffer[128]={0};
while(1)
{
memset(buffer,0,128);
cout<<"input to send:";
cin>>buffer;
if(buffer[0] == 'q')
break;
int nBytes;
if ((nBytes = send(client, buffer, strlen(buffer),0))
== SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
printf("Blocking\n");
Sleep(100);
break;
}
else
{
cout<<"send error:"<<GetLastError()<<endl;
closesocket(client);
break;
}
}
cout<<"send success .."<<endl;
}
WSACleanup();
return 0;
}