// 另一个重叠io.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//
#include <iostream>
#include <tchar.h>
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
// TODO: 在此处引用程序要求的附加头文件
#define DATA_BUFSIZE 1024 // 接收缓冲区大小
#define MAXSESSION 10000 // 最大连接数
typedef struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
DWORD Flags = 0; // WSARecv的参数
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,LPWSAOVERLAPPED Overlapped, DWORD InFlags);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
int ret;
SOCKET ListenSocket = INVALID_SOCKET;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
ListenSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(10000);
bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
ret= listen(ListenSocket,100);
if(ret==SOCKET_ERROR)
{
printf("listen失败 错误id:%d",ret);
return false ;
}
printf("listenning...\n");
SOCKADDR_IN ClientAddr;
int addr_length=sizeof(ClientAddr);
while (TRUE)
{
//新建一个客户数据结构
LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION;
//接受新客户连接
if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET)
{
printf("accept ip:%s port:%d\n",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
SI->DataBuf.buf = new char[DATA_BUFSIZE]; //可以在SI结构里增加一个char szMSG让DataBuf.buf指向他.
SI->DataBuf.len = DATA_BUFSIZE;
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
//执行一个异步接收操作,当客户发来信息时,将自动执行WorkerRoutine
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
continue;
}
}
}
}
return FALSE;
}
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
LPSOCKET_INFORMATION SI = (LPSOCKET_INFORMATION)Overlapped;
if (Error != 0 || BytesTransferred == 0)
{
printf("cliekt id:%d disconnect\n",SI->Socket);
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
//使用数据
printf("call back:%s\n",SI->DataBuf.buf);
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("cliekt id:%d disconnect\n",SI->Socket);
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
}
}
void main()
{
HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL);
WaitForSingleObject(hThreads,INFINITE);
printf("exit\n");
CloseHandle(hThreads);
}
#include "stdafx.h"
#include <iostream>
#include <tchar.h>
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define MSGSIZE 1024
#define PORT 10000
typedef struct
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char szMessage[MSGSIZE];//
DWORD NumberOfBytesRecvd;
DWORD Flags;
SOCKET sClient;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
void CALLBACK CompletionROUTINE(DWORD dwError,
DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags)
{
LPPER_IO_OPERATION_DATA lpPerIOData = (LPPER_IO_OPERATION_DATA)lpOverlapped;
SOCKET sock=lpPerIOData->sClient;
if (dwError != 0 || cbTransferred == 0)
{
// Connection was closed by client
closesocket(lpPerIOData->sClient);
printf("一个客户退出 socket id:%d\r\n",lpPerIOData->sClient);
//释放客户对应的结构内存
delete lpPerIOData;
lpPerIOData=NULL;
}
else
{
printf("recv sock:%d size:%d\n",sock,cbTransferred);
//在这里处理接收的数据,然后发送...并重置这个客户socket异步接收操作..
//lpPerIOData->szMessage[cbTransferred] = '\0';
//send(lpPerIOData->sClient, lpPerIOData->szMessage, cbTransferred, 0);
// Launch another asynchronous operation
memset(&lpPerIOData->overlap, 0, sizeof(WSAOVERLAPPED));
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
WSARecv(lpPerIOData->sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
CompletionROUTINE);
}
}
void GetError(DWORD error) //返回错误信息
{
switch(error)
{
case WSANOTINITIALISED:
printf("初始化错误\r\n");
break;
case WSAENOTCONN:
printf("对方没有启动\r\n");
break;
case WSAEWOULDBLOCK :
printf("对方已经关闭\r\n");
break;
case WSAECONNREFUSED:
printf("对方没打开端口\r\n");
break;
case WSAENOTSOCK:
printf("在一个非套接字上尝试了一个操作\r\n");
break;
case WSAEADDRINUSE:
printf("特定的地址已在使用中\r\n");
break;
case WSAECONNRESET:
printf("与主机的连接被关闭\r\n");
break;
default:
printf("一般错误,连接出现异常断开\r\n");
}
}
int main()
{
WSADATA wsaData;
SOCKET sListen;
SOCKADDR_IN local, client;
int iaddrSize = sizeof(SOCKADDR_IN);
// Initialize Windows Socket library
int ret= WSAStartup(0x0202, &wsaData);
if(ret!=0)
{
printf("socket WSAStartup Error!\r\n");
return 1;
}else printf("socket WSAStartup OK!\r\n");
// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
//绑定一个套接字到本机的地址
ret= bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
if(ret == SOCKET_ERROR)
{ //绑定错误
printf("Binding Error\r\n");
return FALSE;
}
// Listen
ret= listen(sListen, 3);
if(ret==SOCKET_ERROR)
{
printf("listen失败 错误原因:",ret=WSAGetLastError());
GetError(ret);
return false ;
}
printf("listen OK!\r\nWaiting Client Connect\n");
while (TRUE)
{
// Accept a connection
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
SOCKET g_sNewClientConnection;
g_sNewClientConnection = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
// Launch an asynchronous operation for new arrived connection
lpPerIOData=new PER_IO_OPERATION_DATA();
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->sClient = g_sNewClientConnection;
ret= WSARecv(lpPerIOData->sClient,//客户socket
&lpPerIOData->Buffer, //存放接收数据的
1, //dwBufferCount [in] Number of WSABUF structures in the lpBuffers array.
&lpPerIOData->NumberOfBytesRecvd,//存放接收数据的字节数
&lpPerIOData->Flags,
&lpPerIOData->overlap,
CompletionROUTINE);
//如果接收的数据超过MSGSIZE 系统就会多次调用CompletionROUTINE,直到接收完..
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
}
}