求购(socket)多线程原码,谢谢! 哪一种方法?有异步调用的,有完成端口的,有发消息的,还有通过用select来实现单线程管理多个socket连接的.如果在收到一个连接时就开一个线程,这种方法太土了,大型项目都不会这么做的。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 哦,顺便介绍一本书,<<winsock 网络核心编程>>,看过之后,你会对这些模型了如指掌。 哈,我忘了写地址啦:[email protected]最好是异步的,各位谢谢了! 参考一下我写的代码吧,多线程#include "ESocket.h"//*******************************************************************************////服务器端代码ESocketServer::ESocketServer(){ m_bInit = TRUE; m_MainSocket = 0; NewExchange = DefHandle; WORD wVersionRequested; int ret; wVersionRequested = MAKEWORD(1,1); ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0) { m_bInit = FALSE; return; } // The low byte is the major version and the high byte is the minor version if( LOBYTE(wsaData.wVersion) < 1 ) //如果主版本号小于1 { WSACleanup(); m_bInit = FALSE; return; }}ESocketServer::~ESocketServer(){ if(m_bInit) //m_bInit == TURE WSACleanup();}int ESocketServer::InitSvr(unsigned short port){ if(!m_bInit) return FALSE; SOCKADDR_IN sin; m_MainSocket = socket(AF_INET,SOCK_STREAM,0); //建立TCP连接 if(m_MainSocket == INVALID_SOCKET) return FALSE; sin.sin_family = AF_INET; sin.sin_port = htons(port); //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面) sin.sin_addr.s_addr = htonl(INADDR_ANY); if( bind(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) ) { closesocket(m_MainSocket); m_MainSocket = 0; return FALSE; } if( listen(m_MainSocket,5) ) { closesocket(m_MainSocket); m_MainSocket = 0; return FALSE; } return TRUE;}void ESocketServer::DefHandle(SOCKET skt){ //默认的仅仅是关闭新开的socket closesocket(skt);}int ESocketServer::RunLoop(){ if(m_MainSocket == 0) return FALSE; SOCKET newskt; SOCKADDR tcpaddr; int len; len = sizeof(tcpaddr); memset(&tcpaddr,0,len); while(1) { newskt = accept(m_MainSocket,&tcpaddr,&len); if( newskt != INVALID_SOCKET ) { NewExchange(newskt); } Sleep(100); } return TRUE;}//*******************************************************************************////客户端代码ESocketClient::ESocketClient(){ m_bInit = TRUE; ExchangeData = DefHandle; WORD wVersionRequested; int ret; wVersionRequested = MAKEWORD(1,1); ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0) { m_bInit = FALSE; return; } if( LOBYTE(wsaData.wVersion) < 1 ) { WSACleanup(); m_bInit = FALSE; return; }}ESocketClient::~ESocketClient(){ if(m_bInit) //m_bInit == TURE WSACleanup();}int ESocketClient::InitClient(char * IpAddr,unsigned int port){ if(!m_bInit) return FALSE; SOCKADDR_IN sin; m_MainSocket = socket(AF_INET,SOCK_STREAM,0); //建立TCP连接 if(m_MainSocket == INVALID_SOCKET) return FALSE; sin.sin_family = AF_INET; sin.sin_port = htons(port); //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面) sin.sin_addr.s_addr = inet_addr(IpAddr); if( connect(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) == SOCKET_ERROR ) { closesocket(m_MainSocket); return FALSE; } return TRUE;}void ESocketClient::DefHandle(SOCKET skt){ //默认的仅仅是关闭新开的socket closesocket(skt);}int ESocketClient::RunLoop(){ if(m_MainSocket == 0) return FALSE; ExchangeData(m_MainSocket); return TRUE;} 还有头文件//*********************************************************************//// //// 并发的基于socket的服务器 (Windows Socket 1.1) //// //// Author:dah 2001/10/10 //// ////*********************************************************************//#ifndef __ESOCKET__DAH__2001_10_10__#define __ESOCKET__DAH__2001_10_10__#include "winsock.h"//服务器策略//自动启动并拥有多线程功能class ESocketServer{public: ESocketServer(); ~ESocketServer();public: //返回值 TRUE 为成功, FALSE 为失败 int InitSvr(unsigned short port); //启动服务器(事实上只能运行一次) int RunLoop(); //程序主循环 static void DefHandle(SOCKET skt); //默认处理函数 void (* NewExchange)(SOCKET skt); //处理新的客户端,回调函数private: int m_bInit; //是否已经成功初始化 WSADATA wsaData; SOCKET m_MainSocket; //主Socket(第一个被生成的)};//客户端策略//由用户启动线程并调用ESocketClient::Run(),Run中已经包含了while循环class ESocketClient{public: ESocketClient(); ~ESocketClient();public: //返回值 TRUE 为成功, FALSE 为失败 int InitClient(char * IpAddr,unsigned int port); int RunLoop(); //程序主循环 static void DefHandle(SOCKET skt); //默认处理函数 void (* ExchangeData)(SOCKET skt); //处理新的客户端,回调函数private: int m_bInit; //是否已经成功初始化 WSADATA wsaData; SOCKET m_MainSocket; //Socket句柄};#endif to gameboy999(我心迷茫):非常感谢你的关注,可我看了你的代码以后,好象不是多线程处理的,在服务器端,你accept后调用一函数,那函数是的代码可以贴出来吗?同样在客户端的ExchangeData()函数可以贴出来我参考一下,谢谢! 哦,我上面的模型是可以写成 并发 或者 重复 的就看回调函数写成什么样子。给你部分代码(就基于多线程的吧)例如服务器端//******************************************************************************//// by dah 2001/10/11UINT HandleLoop(LPVOID pParam){ SOCKET skt = * (SOCKET *)pParam; CFile file; //针对每个用户开一个CFile即可 FileList filelist; //初始化filelist InitFileList(file,filelist); char buf[2049]; int rval = 0; do { memset(buf,0,2049); //注:8192字节是局域网上面能一次传输的最大字节数 rval = recv(skt,buf,2048,0); if(rval >0) { AnalyzePacket(skt,buf,rval,file,filelist); } Sleep(50); } while( rval >0 ); //while ( rval != 0 && rval != SOCKET_ERROR ); g_ThreadNum--; CString cs; cs.Format("Socket:%d ended!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum); ShowContent((LPCTSTR)cs); return 0;}//HandleNew可以决定是采用轮循还是并发void HandleNew(SOCKET skt){ AfxBeginThread(HandleLoop,&skt); Sleep(300); //这里Sleep 300秒是必须的! g_ThreadNum++; CString cs; cs.Format("Socket:%d started!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum); ShowContent((LPCTSTR)cs);}UINT SvrThread(LPVOID pParam){ g_ThreadNum = 0; //主侦听线程不算 CString cs; cs.Format("服务器启动.......\r\n"); ShowContent((LPCTSTR)cs); ESocketServer svr; svr.NewExchange = HandleNew; svr.InitSvr(8888); return svr.RunLoop();}然后在需要启动服务器的地方启动SvrThread线程就可以了 There are many good examples about "Http Server with Multi-thread capability" on website codegugu. 第一次面试别人 关于对话框显示的两个小问题,麻烦进来看看哈 求证:1、对话框的 列表框控件上显示的内容是否在始终保存在一块内存区域中,因为当托动对话框时需要重绘;2、是不是列表框中始终无法显示大小大于内存容量的内容? 希望高手能够指教一下!!谢谢 想学好VC++,请给点建义 请问怎样把一个Icon写到RichEditor中?谢谢! 急 高手帮忙 音频媒体格式转换 sos!一个C++的菜问题困了我一天了,大虾救命哦 请教大虾高见:应用网络架构一般如何设计? 快死了,分割视的问题,帮帮忙吧 请教大侠,如何获得主线程指针呢? 多线程问题111,请多指教!
最好是异步的,各位谢谢了!
#include "ESocket.h"//*******************************************************************************//
//服务器端代码
ESocketServer::ESocketServer()
{
m_bInit = TRUE;
m_MainSocket = 0;
NewExchange = DefHandle; WORD wVersionRequested;
int ret; wVersionRequested = MAKEWORD(1,1);
ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0)
{
m_bInit = FALSE;
return;
} // The low byte is the major version and the high byte is the minor version
if( LOBYTE(wsaData.wVersion) < 1 ) //如果主版本号小于1
{
WSACleanup();
m_bInit = FALSE;
return;
}
}ESocketServer::~ESocketServer()
{
if(m_bInit) //m_bInit == TURE
WSACleanup();
}int ESocketServer::InitSvr(unsigned short port)
{
if(!m_bInit) return FALSE; SOCKADDR_IN sin;
m_MainSocket = socket(AF_INET,SOCK_STREAM,0); //建立TCP连接 if(m_MainSocket == INVALID_SOCKET)
return FALSE; sin.sin_family = AF_INET;
sin.sin_port = htons(port); //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面)
sin.sin_addr.s_addr = htonl(INADDR_ANY); if( bind(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) )
{
closesocket(m_MainSocket);
m_MainSocket = 0;
return FALSE;
} if( listen(m_MainSocket,5) )
{
closesocket(m_MainSocket);
m_MainSocket = 0;
return FALSE;
} return TRUE;
}void ESocketServer::DefHandle(SOCKET skt)
{
//默认的仅仅是关闭新开的socket
closesocket(skt);
}int ESocketServer::RunLoop()
{
if(m_MainSocket == 0) return FALSE; SOCKET newskt;
SOCKADDR tcpaddr;
int len;
len = sizeof(tcpaddr);
memset(&tcpaddr,0,len);
while(1)
{
newskt = accept(m_MainSocket,&tcpaddr,&len);
if( newskt != INVALID_SOCKET )
{
NewExchange(newskt);
}
Sleep(100);
}
return TRUE;
}//*******************************************************************************//
//客户端代码
ESocketClient::ESocketClient()
{
m_bInit = TRUE;
ExchangeData = DefHandle; WORD wVersionRequested;
int ret; wVersionRequested = MAKEWORD(1,1);
ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0)
{
m_bInit = FALSE;
return;
} if( LOBYTE(wsaData.wVersion) < 1 )
{
WSACleanup();
m_bInit = FALSE;
return;
}}ESocketClient::~ESocketClient()
{
if(m_bInit) //m_bInit == TURE
WSACleanup();
}int ESocketClient::InitClient(char * IpAddr,unsigned int port)
{
if(!m_bInit) return FALSE; SOCKADDR_IN sin;
m_MainSocket = socket(AF_INET,SOCK_STREAM,0); //建立TCP连接 if(m_MainSocket == INVALID_SOCKET)
return FALSE; sin.sin_family = AF_INET;
sin.sin_port = htons(port); //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面)
sin.sin_addr.s_addr = inet_addr(IpAddr); if( connect(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) == SOCKET_ERROR )
{
closesocket(m_MainSocket);
return FALSE;
}
return TRUE;
}void ESocketClient::DefHandle(SOCKET skt)
{
//默认的仅仅是关闭新开的socket
closesocket(skt);
}int ESocketClient::RunLoop()
{
if(m_MainSocket == 0) return FALSE; ExchangeData(m_MainSocket);
return TRUE;
}
//*********************************************************************//
// //
// 并发的基于socket的服务器 (Windows Socket 1.1) //
// //
// Author:dah 2001/10/10 //
// //
//*********************************************************************//#ifndef __ESOCKET__DAH__2001_10_10__
#define __ESOCKET__DAH__2001_10_10__#include "winsock.h"//服务器策略
//自动启动并拥有多线程功能
class ESocketServer
{
public:
ESocketServer();
~ESocketServer();public:
//返回值 TRUE 为成功, FALSE 为失败
int InitSvr(unsigned short port); //启动服务器(事实上只能运行一次)
int RunLoop(); //程序主循环 static void DefHandle(SOCKET skt); //默认处理函数
void (* NewExchange)(SOCKET skt); //处理新的客户端,回调函数
private:
int m_bInit; //是否已经成功初始化
WSADATA wsaData;
SOCKET m_MainSocket; //主Socket(第一个被生成的)};//客户端策略
//由用户启动线程并调用ESocketClient::Run(),Run中已经包含了while循环
class ESocketClient
{
public:
ESocketClient();
~ESocketClient();public:
//返回值 TRUE 为成功, FALSE 为失败
int InitClient(char * IpAddr,unsigned int port);
int RunLoop(); //程序主循环
static void DefHandle(SOCKET skt); //默认处理函数
void (* ExchangeData)(SOCKET skt); //处理新的客户端,回调函数
private:
int m_bInit; //是否已经成功初始化
WSADATA wsaData;
SOCKET m_MainSocket; //Socket句柄
};#endif
的ExchangeData()函数可以贴出来我参考一下,谢谢!
例如服务器端
//******************************************************************************//
// by dah 2001/10/11
UINT HandleLoop(LPVOID pParam)
{
SOCKET skt = * (SOCKET *)pParam;
CFile file; //针对每个用户开一个CFile即可
FileList filelist; //初始化filelist
InitFileList(file,filelist); char buf[2049];
int rval = 0;
do
{
memset(buf,0,2049);
//注:8192字节是局域网上面能一次传输的最大字节数
rval = recv(skt,buf,2048,0);
if(rval >0)
{
AnalyzePacket(skt,buf,rval,file,filelist);
}
Sleep(50);
}
while( rval >0 ); //while ( rval != 0 && rval != SOCKET_ERROR ); g_ThreadNum--; CString cs;
cs.Format("Socket:%d ended!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum);
ShowContent((LPCTSTR)cs); return 0;
}//HandleNew可以决定是采用轮循还是并发
void HandleNew(SOCKET skt)
{
AfxBeginThread(HandleLoop,&skt);
Sleep(300); //这里Sleep 300秒是必须的! g_ThreadNum++;
CString cs;
cs.Format("Socket:%d started!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum);
ShowContent((LPCTSTR)cs);
}UINT SvrThread(LPVOID pParam)
{
g_ThreadNum = 0; //主侦听线程不算
CString cs;
cs.Format("服务器启动.......\r\n");
ShowContent((LPCTSTR)cs); ESocketServer svr;
svr.NewExchange = HandleNew;
svr.InitSvr(8888);
return svr.RunLoop();
}
然后在需要启动服务器的地方启动SvrThread线程就可以了