移动开发 架构设计 编程语言 互联网 开发经验 Web前端
开发杂谈 系统运维 研发管理 数据库 云 计 算 Java开发
首页 开发总结 移动开发 编程语言 开发经验 Java开发
 当前位置:首页 > 完成端口服务器源码 > 正文显示
 最新推荐文章
互斥与临界区的比较 完成端口测试服务器功能的客户端 完成端口服务器源码 POW工作量证明原理
科大迅飞合成发音人列表 CreateFile和ANSI 获取扩展sd卡跟路径 android基础总结 内部存储
Android 获取系统各个目录 Android遍历手机内所有文件 Android权限管理之Perm Android教程 使用Ecli
Android SDK版本和AD 搭建最新版本的Android开发 SetThreadAffinit 直接显示图片
完成端口服务器源码   (32)


//完成端口服务器源码
#pragma comment(lib,"ws2_32.lib")
#define BUFFER_SIZE 4096
#define PORT 9090
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3

HANDLE hCompletion = NULL;
typedef struct _PER_HANDLE_DATA
{
SOCKET sock;
sockaddr_in si;
}PER_HANDLE_DATA,*PPER_HANDLE_DATA;

typedef struct _PER_IO_DATA
{
OVERLAPPED overlapped;
WSABUF wsabuf;
char buffer[BUFFER_SIZE];
int operationType;
}PER_IO_DATA,*PPER_IO_DATA;

typedef struct _PER_THREAD_DATA
{
HANDLE hCompletion;
int nThreadID;
}PER_THREAD_DATA, *PPER_THREAD_DATA;

DWORD WINAPI ServerThread(LPVOID lParam);

int serverRun()
{
WSADATA wsa;
WSAStartup(MAKEWORD(2,2), &wsa);
//创建一个完成端口
hCompletion=::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
//创建工作线程
for(int i = 0; i < 3; i++)
{
PER_THREAD_DATA *td = new PER_THREAD_DATA();
td->hCompletion = hCompletion;
td->nThreadID = i;
HANDLE h_DoThread = CreateThread(NULL, 0, ServerThread, (LPVOID)td, 0, 0);
::CloseHandle(h_DoThread);
}

SOCKET sListen = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(PORT);
si.sin_addr.S_un.S_addr = INADDR_ANY;
bind(sListen, (SOCKADDR *)&si, sizeof(SOCKADDR));
listen(sListen, 5);

while(TRUE)
{
sockaddr_in RemoteInfo;
int RemoteLen = sizeof(sockaddr_in);
afx_message(1, "accept");

SOCKET AcceptClient = accept(sListen,(sockaddr*)&RemoteInfo, &RemoteLen);
//每当有新连接时,将为其创建PER_HANDLE_DATA数据和PER_IO_DATA数据。
PPER_HANDLE_DATA pPerHandleData = new PER_HANDLE_DATA();
pPerHandleData->sock = AcceptClient;
memcpy(&(pPerHandleData->si), &RemoteInfo, sizeof(sockaddr));

//将套接字句柄与完成端口相关联
CreateIoCompletionPort(
(HANDLE)pPerHandleData->sock, hCompletion,
(DWORD)pPerHandleData, 0);

PPER_IO_DATA pPer_IO_Data = new PER_IO_DATA();
pPer_IO_Data->operationType = OP_READ;
//WSARecv等函数中,缓冲区必须是WSABUF,下面对WSABUF进行初始化
pPer_IO_Data->wsabuf.buf = pPer_IO_Data->buffer;
pPer_IO_Data->wsabuf.len = BUFFER_SIZE;
DWORD dwRecv;
DWORD dwFlags = 0;
memset(&pPer_IO_Data->overlapped, 0, sizeof(pPer_IO_Data->overlapped));

//投递一个接收请求
afx_message(1, "main WSARecv OP_READ");
::WSARecv(pPerHandleData->sock, &(pPer_IO_Data->wsabuf),
1, &dwRecv, &dwFlags, &(pPer_IO_Data->overlapped), NULL);
}
return 0;
}

DWORD WINAPI ServerThread(LPVOID lParam)
{
PER_THREAD_DATA *td = (PER_THREAD_DATA *)lParam;
HANDLE hCompletion = td->hCompletion;
int nId = td->nThreadID;
CString s;
s.Format("thread id=%d, completion=%d", nId, hCompletion);
afx_message(1, s);

CString strThreadID;
strThreadID.Format(" threadid=%d ", nId);

DWORD dwTrans;
PPER_HANDLE_DATA pPer_Handle_Data;
PPER_IO_DATA pPer_IO_Data;
while (TRUE)
{
bool bOk = GetQueuedCompletionStatus(hCompletion, &dwTrans, (LPDWORD)&pPer_Handle_Data, (LPOVERLAPPED*)&pPer_IO_Data, INFINITE);
CString strType;
if(pPer_IO_Data->operationType == 1)
strType = "OP_READ";
if(pPer_IO_Data->operationType == 2)
strType = "OP_WRITE";

s.Format("work thread loop[%d], ret=%d, dwTrans=%d, oper=%d(%s)",
nId, bOk, dwTrans, pPer_IO_Data->operationType, strType);
afx_message(1, s);

if(!bOk)
{
afx_message(1, strThreadID + "work, socket close");
closesocket(pPer_Handle_Data->sock);
delete pPer_Handle_Data;
delete pPer_IO_Data;
continue;
}

//套接字被对方关闭
if(dwTrans == 0 && (pPer_IO_Data->operationType == OP_READ || pPer_IO_Data->operationType == OP_WRITE) )
{
afx_message(1, strThreadID + "work, socket close2");
closesocket(pPer_Handle_Data->sock);
delete pPer_Handle_Data;
delete pPer_IO_Data;
continue;
}

switch(pPer_IO_Data->operationType)
{
case OP_READ: //调用wsarecv后数据己收到buffer中,调用此代码
{
afx_message(1, strThreadID + "OP_READ-1");
pPer_IO_Data->buffer[dwTrans]='\0';
CString s;
s.Format("recv data :%s", pPer_IO_Data->buffer);
afx_message(1, strThreadID + s);

s = "[" + s + "ok]";
memset(pPer_IO_Data->buffer, 0, sizeof(pPer_IO_Data->buffer));

strcpy(pPer_IO_Data->buffer, s);
pPer_IO_Data->wsabuf.len = s.GetLength();
pPer_IO_Data->wsabuf.buf = pPer_IO_Data->buffer;
memset(&(pPer_IO_Data->overlapped), 0, sizeof(pPer_IO_Data->overlapped));

DWORD SendBytes = 0;
DWORD flags = 0;
pPer_IO_Data->operationType = OP_WRITE;
WSASend(pPer_Handle_Data->sock, &(pPer_IO_Data->wsabuf),
1, &SendBytes,flags,&(pPer_IO_Data->overlapped),NULL);

s.Format(" len=%d", s.GetLength());
afx_message(1, strThreadID + "WSASend OP_WRITE" + s);
}
break;

case OP_WRITE: //调用wsasend后,有部分数据被发送之后调用此代码
{
afx_message(1, strThreadID + "OP_WRITE-2");
memset(pPer_IO_Data->buffer, 0, sizeof(pPer_IO_Data->buffer));
pPer_IO_Data->operationType = OP_READ;
//WSARecv等函数中,缓冲区必须是WSABUF,下面对WSABUF进行初始化
memset(&(pPer_IO_Data->overlapped), 0, sizeof(pPer_IO_Data->overlapped));
pPer_IO_Data->wsabuf.buf = pPer_IO_Data->buffer;
pPer_IO_Data->wsabuf.len = BUFFER_SIZE;
afx_message(1, strThreadID + "WSARecv OP_READ");
DWORD flags = 0;
WSARecv(pPer_Handle_Data->sock, &pPer_IO_Data->wsabuf,1,&dwTrans,&flags,&(pPer_IO_Data->overlapped),NULL);
}
break;

case OP_ACCEPT:
afx_message(1, strThreadID + "OP_ACCEPT-3");
break;
}
}

afx_message(1, strThreadID + "end thread");
return 0;
}
 最热文章
http://www.3 获取扩展sd卡跟路径 Android遍历手机内 android基础总结
Android 获取系统 科大迅飞合成发音人列表 搭建最新版本的Andro Android SDK版
直接显示图片 Android教程 使用 Android权限管理之 SetThreadAff
实时视频传输的关键技术 Zlib库对网页中def VC++内存泄漏的检测与 C++中的STL中map
在Visual C++中 vc, c++ stl C++中的STL中map VC 获取 程序窗口大小
移动开发 架构设计 编程语言 互联网 开发经验 Web前端
开发杂谈 系统运维 研发管理 数据库 云 计 算 Java开发
 网站联系 QQ: 121756557 E-Mail: 121756557@qq.com ©2018