分享
 
 
 

自己封装socket(更新啦)

王朝other·作者佚名  2007-01-01
窄屏简体版  字體: |||超大  

CAsynSocket似乎总难满足要求,不能跨线程使用应该是它的致命伤,直接使用socket是最好的办法,这也是许多大牛们推荐的方法。为了避免重复劳动,自己封装了一个CMySocket类,希望能像CAsynSocket一样使用(现在还不可能了,偶也是初学,只有慢慢完善,也许有一天能接近CAsynSocket ),既然是自己封装的类,是否线程安全就自己说了算了,呵呵。

目前实现如下功能:

创建socket、数据收发(TCP和UDP)、收发缓冲区大小设置等。

IO模型采用WSAEventSelect机制。

用它实现了局域网的聊天程序,挺好用。如有不恰当的地方,请给我留言,我会将其逐步完善!

使用方法:

继承CMySocket类,重载OnAccept、OnReceive等函数(和CAsyncSocket方法相同)。不用调用AfxSocketInit函数,因为该函数所作工作在我封装的代码中已完成。

下面是代码

******************************头文件 MySocket.h***********************

#ifndef __MYSOCKET_H__

#define __MYSOCKET_H__

#include <WINSOCK2.H>

#define MAX_SOCKET 64

#pragma comment(lib,"Ws2_32.lib")

typedef struct tagClient

{

sockaddr addr;

SOCKET sock;

}TClient;

class CMySocket

{

public:

CMySocket();

CMySocket(const CMySocket&);

~CMySocket();

static int StartUp();

int Create(int port,int socket_type,long lEvent=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);

int Close();

int Listen(int backlog=SOMAXCONN);

int Accept(CMySocket* pSocket,struct sockaddr* addr);

int Connect(const char* IP,int port);

int Receive(char* buf,int len);

int Receive(char* buf,int len,char* IP,int* port);

int Send(char* buf,int len);

int Send(char* buf,int len,const char* IP,int port);

int GetRcvBufSize(int* bufsize,int* len);

int GetSndBufSize(int* bufsize,int* len);

int SetRcvBufSize(int* bufsize,int len);

int SetSndBufSize(int* bufsize,int len);

CMySocket operator = (CMySocket& mySocket1);

virtual void OnAccept(int errorcode);

virtual void OnConnect(int errorcode);

virtual void OnReceive(int errorcode);

virtual void OnSend(int errorcode);

virtual void OnClose(int errorcode);

static void GetSocketAddr(struct sockaddr* addr);

static void RemoveSocket(SOCKET s);

SOCKET m_socket;

int m_nSocketType;

long m_lEvent;

BOOL m_bThreadStarted;

BOOL m_bEndTread;

static int m_nClientNum;

static TClient clientList[MAX_SOCKET];

static SOCKET socketArray[MAX_SOCKET];

static WSAEVENT eventArrray[MAX_SOCKET];

static int m_totalSocket;

static DWORD m_dwIndex;

static CRITICAL_SECTION m_cs;

protected:

static int m_nInstnum;

static BOOL m_bStartUp;

static BOOL m_bInitCS;

private:

};

#endif

***************************代码实现 MySocket.cpp*****************************

#include "stdafx.h"

#include "MySocket.h"

#include <process.h>

void SocketThread(void* parm);

TClient CMySocket::clientList[MAX_SOCKET];

SOCKET CMySocket::socketArray[MAX_SOCKET];

WSAEVENT CMySocket::eventArrray[MAX_SOCKET];

int CMySocket::m_totalSocket = 0;

int CMySocket::m_nInstnum = 0;

int CMySocket::m_nClientNum = 0;

DWORD CMySocket::m_dwIndex = 0;

BOOL CMySocket::m_bStartUp = FALSE;

BOOL CMySocket::m_bInitCS = FALSE;

CRITICAL_SECTION CMySocket::m_cs;

CMySocket::CMySocket()

{

m_socket = INVALID_SOCKET;

m_bThreadStarted = FALSE;

m_bEndTread = FALSE;

m_nInstnum++;

if (!m_bInitCS)

{

InitializeCriticalSection(&m_cs);

m_bInitCS = TRUE;

}

}

CMySocket::CMySocket(const CMySocket& myScoket)

{

m_socket = myScoket.m_socket;

m_nSocketType = myScoket.m_nSocketType;

}

CMySocket::~CMySocket()

{

m_nInstnum--;

if (m_socket != INVALID_SOCKET)

{

closesocket(m_socket);

}

if (!m_nInstnum)

{

WSACleanup();

m_bStartUp = FALSE;

}

}

int CMySocket::StartUp()

{

if (!m_bStartUp)

{

WSADATA wsaData;

if (WSAStartup(WINSOCK_VERSION,&wsaData))

{

int err = WSAGetLastError();

return err;

}

}

return 0;

}

int CMySocket::Create(int port,int socket_type,long lEvent)

{

if (!m_bStartUp)

{

StartUp();

}

if (m_socket != INVALID_SOCKET)

{

return 0;

}

m_nSocketType = socket_type;

m_socket = socket(AF_INET,m_nSocketType,0);

if (m_socket == INVALID_SOCKET)

{

int err = WSAGetLastError();

return err;

}

else

{

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.S_un.S_addr = INADDR_ANY;

addr.sin_port = htons(port);

if (bind(m_socket,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

}

WSAEVENT wsaEvent = WSACreateEvent();

if (WSAEventSelect(m_socket,wsaEvent,lEvent))

{

int err = WSAGetLastError();

return err;

}

EnterCriticalSection(&m_cs);

socketArray[m_totalSocket] = m_socket;

eventArrray[m_totalSocket] = wsaEvent;

m_totalSocket++;

LeaveCriticalSection(&m_cs);

m_bEndTread = FALSE;

if (_beginthread(SocketThread,0,this) == -1)

{

return -1;

}

int loopnum = 0;

while (!m_bThreadStarted)

{

loopnum++;

if (loopnum > 200)

{

return -1;

}

Sleep(10);

}

return 0;

}

int CMySocket::Close()

{

RemoveSocket(m_socket);

if (closesocket(m_socket) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

m_socket = INVALID_SOCKET;

m_bEndTread = TRUE;

return 0;

}

int CMySocket::Listen(int backlog)

{

if (listen(m_socket,backlog) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

return 0;

}

int CMySocket::Accept(CMySocket* pSocket,struct sockaddr* addr)

{

SOCKET sock;

int len = sizeof(struct sockaddr);

if ((sock = accept(m_socket,addr,&len)) == INVALID_SOCKET)

{

int err = WSAGetLastError();

return err;

}

pSocket->m_socket = sock;

pSocket->m_nSocketType = SOCK_STREAM;

WSAEVENT wsaEvent = WSACreateEvent();

if (WSAEventSelect(sock,wsaEvent,FD_READ | FD_CLOSE))

{

int err = WSAGetLastError();

return err;

}

EnterCriticalSection(&m_cs);

socketArray[m_totalSocket] = sock;

eventArrray[m_totalSocket] = wsaEvent;

m_totalSocket++;

int index = m_nClientNum;

clientList[index].addr = *addr;

clientList[index].sock = sock;

m_nClientNum++;

LeaveCriticalSection(&m_cs);

return 0;

}

int CMySocket::Connect(const char* IP,int port)

{

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.S_un.S_addr = inet_addr(IP);

addr.sin_port = htons(port);

if (connect(m_socket,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

return 0;

}

void CMySocket::RemoveSocket(SOCKET s)

{

int i,j;

EnterCriticalSection(&m_cs);

int totalSocket = m_totalSocket;

for (i=0;i<totalSocket;i++)

{

if (CMySocket::socketArray[i] == s)

{

for (j=i;j<totalSocket-1;j++)

{

socketArray[j] = socketArray[j+1];

eventArrray[j] = eventArrray[j+1];

}

m_totalSocket--;

break;

}

}

int num = m_nClientNum;

for (i=0;i<num;i++)

{

if (clientList[i].sock == s)

{

for (j=i;j<num-1;j++)

{

clientList[j].sock = clientList[j+1].sock;

clientList[j].addr = clientList[j+1].addr;

}

m_nClientNum--;

break;

}

}

LeaveCriticalSection(&m_cs);

}

void SocketThread(void* parm)

{

CMySocket *pMySocket = (CMySocket*)parm;

WSANETWORKEVENTS tEvent;

DWORD ret;

DWORD dwIndex;

int errorcode;

int timeout = 10;

pMySocket->m_bThreadStarted = TRUE;

while (1)

{

EnterCriticalSection(&CMySocket::m_cs);

ret = WSAWaitForMultipleEvents(CMySocket::m_totalSocket,CMySocket::eventArrray,FALSE,timeout,FALSE);

LeaveCriticalSection(&CMySocket::m_cs);

if (pMySocket->m_bEndTread)

{

_endthread();

}

if (ret == WSA_WAIT_TIMEOUT)

{

continue;

}

dwIndex = ret;

dwIndex -= WSA_WAIT_EVENT_0;

CMySocket::m_dwIndex = dwIndex;

memset(&tEvent,0,sizeof(WSANETWORKEVENTS));

EnterCriticalSection(&CMySocket::m_cs);

WSAEnumNetworkEvents(CMySocket::socketArray[dwIndex],CMySocket::eventArrray[dwIndex],&tEvent);

WSAResetEvent(CMySocket::eventArrray[dwIndex]);

LeaveCriticalSection(&CMySocket::m_cs);

if (tEvent.lNetworkEvents & FD_CONNECT)

{

errorcode = tEvent.iErrorCode[FD_CONNECT_BIT];

pMySocket->OnConnect(errorcode);

}

else if (tEvent.lNetworkEvents & FD_ACCEPT)

{

errorcode = tEvent.iErrorCode[FD_ACCEPT_BIT];

pMySocket->OnAccept(errorcode);

}

else if (tEvent.lNetworkEvents & FD_READ)

{

DWORD nBytes = 0;

errorcode = tEvent.iErrorCode[FD_READ_BIT];

ioctlsocket(CMySocket::socketArray[dwIndex],FIONREAD,&nBytes);

if (nBytes > 0)

pMySocket->OnReceive(errorcode);

}

else if (tEvent.lNetworkEvents & FD_WRITE)

{

errorcode = tEvent.iErrorCode[FD_WRITE_BIT];

pMySocket->OnSend(errorcode);

}

else if (tEvent.lNetworkEvents & FD_CLOSE)

{

errorcode = tEvent.iErrorCode[FD_CLOSE_BIT];

pMySocket->OnClose(errorcode);

CMySocket::RemoveSocket(CMySocket::socketArray[dwIndex]);

}

else

{

}

}

}

int CMySocket::Receive(char* buf,int len)

{

sockaddr addr;

int size = sizeof(addr);

switch(m_nSocketType)

{

case SOCK_DGRAM:

if (recvfrom(m_socket,buf,len,0,&addr,&size) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

break;

case SOCK_STREAM:

if (recv(m_socket,buf,len,0) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

break;

default:

break;

}

return 0;

}

int CMySocket::Receive(char* buf,int len,char* IP,int* port)

{

sockaddr addr;

int size = sizeof(addr);

sockaddr_in* pAddr_in;

switch(m_nSocketType)

{

case SOCK_DGRAM:

if (recvfrom(m_socket,buf,len,0,&addr,&size) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

pAddr_in = (sockaddr_in*)&addr;

strcpy(IP,inet_ntoa(pAddr_in->sin_addr));

*port = ntohs(pAddr_in->sin_port);

break;

case SOCK_STREAM:

if (recv(m_socket,buf,len,0) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

break;

default:

break;

}

return 0;

}

int CMySocket::Send(char* buf,int len)

{

if (send(m_socket,buf,len,0) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

return 0;

}

int CMySocket::Send(char* buf,int len,const char* IP,int port)

{

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.S_un.S_addr = inet_addr(IP);

addr.sin_port = htons(port);

switch(m_nSocketType)

{

case SOCK_DGRAM:

if (sendto(m_socket,buf,len,0,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

break;

case SOCK_STREAM:

if (send(m_socket,buf,len,0) == SOCKET_ERROR)

{

int err = WSAGetLastError();

return err;

}

break;

default:

break;

}

return 0;

}

int CMySocket::GetRcvBufSize(int* bufsize,int* len)

{

if (getsockopt(m_socket,SOL_SOCKET,SO_RCVBUF,(char*)bufsize,len))

{

int err = WSAGetLastError();

return err;

}

return 0;

}

int CMySocket::GetSndBufSize(int* bufsize,int* len)

{

if (getsockopt(m_socket,SOL_SOCKET,SO_SNDBUF,(char*)bufsize,len))

{

int err = WSAGetLastError();

return err;

}

return 0;

}

int CMySocket::SetRcvBufSize(int* bufsize,int len)

{

if (setsockopt(m_socket,SOL_SOCKET,SO_RCVBUF,(char*)bufsize,len))

{

int err = WSAGetLastError();

return err;

}

return 0;

}

int CMySocket::SetSndBufSize(int* bufsize,int len)

{

if (setsockopt(m_socket,SOL_SOCKET,SO_SNDBUF,(char*)bufsize,len))

{

int err = WSAGetLastError();

return err;

}

return 0;

}

CMySocket CMySocket::operator = (CMySocket& mySocket1)

{

CMySocket newScoket;

newScoket.m_socket = mySocket1.m_socket;

newScoket.m_nSocketType = mySocket1.m_nSocketType;

return newScoket;

}

void CMySocket::GetSocketAddr(struct sockaddr* addr)

{

EnterCriticalSection(&m_cs);

int num = m_nClientNum;

for (int i=0;i<num;i++)

{

if (clientList[i].sock == socketArray[m_dwIndex])

{

*addr = clientList[i].addr;

LeaveCriticalSection(&m_cs);

return;

}

}

addr->sa_data[0] = 0;

LeaveCriticalSection(&m_cs);

}

void CMySocket::OnReceive(int errorcode)

{

}

void CMySocket::OnAccept(int errorcode)

{

}

void CMySocket::OnClose(int errorcode)

{

}

void CMySocket::OnConnect(int errorcode)

{

}

void CMySocket::OnSend(int errorcode)

{

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有