Windows Socket 模型简单例子

整个工程的源码下载地址为

http://download.csdn.net/detail/u012607841/9158527


发送数据测试

.版本 2

.程序集 窗口程序集1

.子程序 __启动窗口_创建完毕



.子程序 _按钮1_被单击

客户1.发送数据 (#常量1)


.子程序 _客户1_数据到达


编辑框1.内容 = 到文本 (客户1.取回数据 ())
标签1.标题 = “文本长度 ” + 到文本 (取文本长度 (编辑框1.内容))

.子程序 _按钮2_被单击
.局部变量 是否成功, 逻辑型

是否成功 = 客户1.连接 (“127.0.0.1”, 8080)
_启动窗口.标题 = 选择 (是否成功, “链接成功”, “链接失败”)


.子程序 __启动窗口_将被销毁

客户1.断开连接 ()




基础类模块源码


#ifndef socket_h__
#define socket_h__

#include <WinSock2.h>
#include <string>
using namespace std;

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



DWORD WINAPI OnRecvThread(LPVOID lpvoid);

class CBuffer
{
public:
	CBuffer()
	{
		
	}
	CBuffer(const CBuffer& buf): m_Data(buf.m_Data)
	{
	}
	~CBuffer()
	{
	}
	VOID AddData(VOID* pData,DWORD nSize)
	{
		string data;
		data.resize(nSize,0);
		CopyMemory((VOID*)data.data(),pData,nSize);
		m_Data += data;
	}
	CBuffer& operator+=(const char* pText)
	{
		m_Data+=pText;
		return*this;
	}
	CBuffer& operator+=(const CBuffer& buf)
	{
		m_Data+=buf.m_Data;
		return*this;
	}
	VOID* GetData()
	{
		return (VOID*)m_Data.data();
	}
	DWORD GetSize()
	{
		return m_Data.size();
	}
private:
	string m_Data;
};

class CAccept
{
public:
	CAccept()
	{

	}
	CAccept(SOCKET s,SOCKADDR_IN ar)
	{
		m_addr = ar;
		m_sAccept = s;
	}
	char* GetIP()
	{
		return inet_ntoa(m_addr.sin_addr);
	}
	int Recv(char* buf,int len)
	{
		return ::recv(m_sAccept,buf,len,0);
	}
	int Send(char* buf,int len)
	{
		return ::send(m_sAccept,buf,len,0);
	}
	SOCKET GetSocket()
	{
		return m_sAccept;
	}
private:
	SOCKET m_sAccept;
	SOCKADDR_IN m_addr;
};


int RecvData(CAccept* pAcp,CBuffer& buf);
int SendData(CAccept* pAcp,CBuffer& buf);


class CSocket
{
public:
	CSocket()
	{
		WORD wVersionRequested;  
		WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的  
		
		wVersionRequested = MAKEWORD( 2, 2 );   // 请求1.1版本的WinSock库  
		int err = WSAStartup( wVersionRequested, &wsaData );
	}
	~CSocket()
	{
		closesocket(sockfd);
		WSACleanup();
	}
	
	bool socket_TCP()
	{
		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		return (INVALID_SOCKET != sockfd);
	}
	bool Bind(u_short uPort)
	{
		/* setting server's socket */
		struct sockaddr_in server_addr;
		server_addr.sin_family = AF_INET;         // IPv4 network protocol
		server_addr.sin_port = htons(uPort);
		server_addr.sin_addr.s_addr = INADDR_ANY; // auto IP detect
		memset(&(server_addr.sin_zero),0, sizeof(server_addr.sin_zero));
		return (::bind(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) != SOCKET_ERROR);
	}
	bool Listen()
	{
		return(::listen(sockfd, SOMAXCONN) != SOCKET_ERROR);
	}
	
	CAccept Accept()
	{
		SOCKADDR_IN client_addr;
		int addr_size = sizeof(struct sockaddr_in);                                         
		
		SOCKET client_fd = ::accept(sockfd, (struct sockaddr *)&client_addr, &addr_size);
		CAccept acp(client_fd,client_addr);
		return acp;
	}
	
	int setsockopt(int optname,const char* optval,int optlen)
	{
		int level = SOL_SOCKET; //原始套接字
		return ::setsockopt(sockfd,level,optname,optval,optlen);
	}
	
private:
	SOCKET sockfd;
};




class CClientBase
{
public:
	CClientBase()
	{

	}
	virtual bool InitServer(unsigned short uPort)
	{
		m_sock.socket_TCP();
		m_sock.Bind(uPort);
		m_sock.Listen();
		return true;
	}
	virtual VOID _OnRun()
	{
	}
	VOID Run()
	{
		m_bRun = TRUE;
		DWORD dwThreadId = 0;
		m_hThread = CreateThread(NULL,NULL,OnRecvThread,(VOID*)this,0,&dwThreadId);
		WaitForSingleObject(m_hThread,INFINITE);
	}
	
	VOID Stop()
	{
		m_bRun = FALSE;
	}
protected:
	
	CSocket m_sock;
	SOCKET sockfd;
	SOCKET client_fd;
	
	HANDLE	m_hThread;
	bool m_bRun;
};


#endif // socket_h__


这个是Select模型


#ifndef DemoSelect_h__
#define DemoSelect_h__


DWORD WINAPI WorkerThread(LPVOID lpParam);


class CClientSelect : public CClientBase
{
public:
	CClientSelect()
	{
	}
	VOID Worker()
	{
		int            i;
		fd_set         fdread;
		int            ret;
		struct timeval tv = {1, 0};
		char           szMessage[MAX_PATH];
		
		while (m_bRun)
		{
			FD_ZERO(&fdread);
			for (i = 0; i < g_iTotalConn; i++)
			{
				FD_SET(g_CliSocketArr[i].GetSocket(), &fdread);
			}
			
			// We only care read event
			ret = select(0, &fdread, NULL, NULL, &tv);
			
			if (ret == 0)
			{
				// Time expired
				printf("超时!\r\n");
				continue;
			}
			for (i = 0; i < g_iTotalConn; i++)
			{
				SOCKET sock = g_CliSocketArr[i].GetSocket();
				if (FD_ISSET(sock, &fdread))
				{
					// A read event happened on g_CliSocketArr[i]
					ret = recv(sock, szMessage, MAX_PATH, 0);
					if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
					{
						// Client socket closed
						printf("Client socket %d closed.\r\n", g_CliSocketArr[i].GetIP());
						closesocket(sock);
						if (i < g_iTotalConn - 1)
						{            
							g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
						}
					}
					else
					{
						// We received a message from client
						szMessage[ret] = '\0';
						send(sock, szMessage, strlen(szMessage), 0);
					}
				}
			}
		}
	}
	virtual VOID _OnRun()
	{
		DWORD       dwThreadId;
		HANDLE hThread = CreateThread(NULL, 0, WorkerThread, this, 0, &dwThreadId); 

		g_iTotalConn = 0;
		while (TRUE)
		{
			CAccept acp = m_sock.Accept();
			// Accept a connection
			printf("Accepted client:%s:\r\n",acp.GetIP());
			// Add socket to g_CliSocketArr
			g_CliSocketArr[g_iTotalConn++] = acp;
		}

		WaitForSingleObject(hThread,INFINITE);
	}
private:

	int    g_iTotalConn ;
	CAccept g_CliSocketArr[FD_SETSIZE];
};


DWORD WINAPI WorkerThread(LPVOID lpParam)
{	
	CClientSelect* pSelect = (CClientSelect*)lpParam;
	pSelect->Worker();
	return 0;
}


#endif // DemoSelect_h__


event模型


#ifndef DemoEvents_h__
#define DemoEvents_h__



DWORD WINAPI EventsWorkerThread(LPVOID lpParam);


class CClientEvents : public CClientBase
{
public:
	CClientEvents()
	{
	}
	VOID Worker()
	{
		int              ret, index;
		WSANETWORKEVENTS NetworkEvents;
		char             szMessage[MAX_PATH];

			while (TRUE)
			{
				ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
				if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
				{
				  continue;
				}

				index = ret - WSA_WAIT_EVENT_0;
				WSAEnumNetworkEvents(g_CliSocketArr[index].GetSocket(), g_CliEventArr[index], &NetworkEvents);

				if (NetworkEvents.lNetworkEvents & FD_READ)
				{
				  // Receive message from client
				  ret = recv(g_CliSocketArr[index].GetSocket(), szMessage, MAX_PATH, 0);
				  if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
				  {
					Cleanup(index);
				  }
				  else
				  {
					szMessage[ret] = '\0';
					send(g_CliSocketArr[index].GetSocket(), szMessage, strlen(szMessage), 0);
				  }
				}

				if (NetworkEvents.lNetworkEvents & FD_CLOSE)
				{
					Cleanup(index);
				}
			}

	}

	virtual VOID _OnRun()
	{
		DWORD       dwThreadId;
		HANDLE hThread = CreateThread(NULL, 0, EventsWorkerThread, this, 0, &dwThreadId); 
		
		g_iTotalConn = 0;
		while (TRUE)
		{

			CAccept acp = m_sock.Accept();
			// Accept a connection
			printf("Accepted client:%s:\r\n",acp.GetIP());
			
			// Associate socket with network event
			g_CliSocketArr[g_iTotalConn++] = acp;
			g_CliEventArr[g_iTotalConn] = WSACreateEvent();
			WSAEventSelect(
				g_CliSocketArr[g_iTotalConn].GetSocket(),
				g_CliEventArr[g_iTotalConn],
				FD_READ | FD_CLOSE);
			g_iTotalConn++;
		 
		}
		
		WaitForSingleObject(hThread,INFINITE);
	}
	void Cleanup(int index)
	{
		closesocket(g_CliSocketArr[index].GetSocket());
		WSACloseEvent(g_CliEventArr[index]);
		
		if (index < g_iTotalConn - 1)
		{
			g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1];
			g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1];
		}
		
		g_iTotalConn--;
	}
private:
	
	int    g_iTotalConn ;
	CAccept g_CliSocketArr[FD_SETSIZE];
	WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
};


DWORD WINAPI EventsWorkerThread(LPVOID lpParam)
{	
	CClientSelect* pSelect = (CClientSelect*)lpParam;
	pSelect->Worker();
	return 0;
}

#endif // DemoEvents_h__





调用代码


#include "stdafx.h"
#include "DemoHttpServer.h"
#include "DemoSelect.h"
#include "DemoEvents.h"

void testDemoHttpServer()
{
	CClientHTTPServer Client;
	Client.InitServer(8080);
	Client.Run();
}
void testDemoSelect()
{
	CClientSelect Client;
	Client.InitServer(8080);
	Client.Run();
}

void testDemoEvent()
{
	CClientEvents Client;
	Client.InitServer(8080);
	Client.Run();
}

int main(char argc, char *argv[])
{
	testDemoEvent();
	return 0;
}       




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值