现在的位置: 首页 > 综合 > 正文

windows下实现socket 的 通讯的 select 模型

2019年01月10日 ⁄ 综合 ⁄ 共 4937字 ⁄ 字号 评论关闭

通讯端点定义类:

 

#pragma once

#include <WinSock2.h>

#define SERVER		1
#define CLIENT		2

#include <iostream>
using namespace std;

class CEndpoint
{
public:
	CEndpoint(void);
	CEndpoint(SOCKET socket, unsigned int type);
	CEndpoint(const CEndpoint &endpoint);
	~CEndpoint(void);
private:
	SOCKET m_socket;
	unsigned int m_type;
public:
	SOCKET getsocket();
	unsigned char gettype();
	bool operator < (const CEndpoint& endpoint) const;
	friend ostream & operator << (ostream& out, const CEndpoint& endpoint)
	{
		out << "socket=" << endpoint.m_socket << " type=" << endpoint.m_type;
		return out;
	}
};


#include "StdAfx.h"
#include "Endpoint.h"


CEndpoint::CEndpoint(void)
{
}

CEndpoint::CEndpoint(SOCKET socket, unsigned int type)
{
	m_socket = socket;
	m_type = type;
}

CEndpoint::CEndpoint(const CEndpoint &endpoint)
{
	m_socket = endpoint.m_socket;
	m_type = endpoint.m_type;
}


CEndpoint::~CEndpoint(void)
{
}

SOCKET CEndpoint::getsocket()
{
	return m_socket;
}

unsigned char CEndpoint::gettype()
{
	return m_type;
}



bool CEndpoint::operator<(const CEndpoint& endpoint) const
{
	if (m_socket < endpoint.m_socket)
	{
		return true;
	}
	else if(m_socket == endpoint.m_socket && m_type < endpoint.m_type)
	{
		return true;
	}
	return false;
}

 

 

 

 

通讯端点管理类:CEndpointset

 

#pragma once

#include "Endpoint.h"
#include <set>

using namespace std;

typedef set<CEndpoint> EPSET;
typedef EPSET::iterator ITERATOR;


class CEndpointset
{
public:
	CEndpointset(void);
	~CEndpointset(void);
private:
	EPSET m_using_epset;
	EPSET m_connection_epset;
	EPSET m_disconnection_epset;
	ITERATOR m_using_li;
public:
	bool insertusing(CEndpoint ep);
	bool insertconnection(CEndpoint ep);
	bool insertdisconnection(CEndpoint ep);
	
	void gofirstusing();
	bool getnextusing(CEndpoint &ep);
	void display();
	
	void resettle(fd_set* fdread, unsigned int* maxfd);
	void reset(fd_set* fdread, unsigned int* maxfd);

};




#include "StdAfx.h"
#include "Endpointset.h"
#include <algorithm>
#include <iostream>
#include <iterator>

CEndpointset::CEndpointset(void)
{
}


CEndpointset::~CEndpointset(void)
{
}


bool CEndpointset::insertusing(CEndpoint ep)
{
	pair<set<CEndpoint>::iterator, bool> Insert_Pair;
	Insert_Pair = m_using_epset.insert(ep);	
	return Insert_Pair.second;
}

bool CEndpointset::insertconnection(CEndpoint ep)
{
	pair<set<CEndpoint>::iterator, bool> Insert_Pair;
	Insert_Pair =m_connection_epset.insert(ep);
	return Insert_Pair.second;
}

bool CEndpointset::insertdisconnection(CEndpoint ep)
{
	pair<set<CEndpoint>::iterator, bool> Insert_Pair;
	Insert_Pair = m_disconnection_epset.insert(ep);
	return Insert_Pair.second;
}

void CEndpointset::resettle(fd_set* fdread, unsigned int* maxfd)
{
	EPSET myset;

	set_union(m_using_epset.begin(), m_using_epset.end(), 
			m_connection_epset.begin(), m_connection_epset.end(), 
			inserter(myset, myset.begin()));
	
	m_using_epset.clear();
	m_using_epset = myset;
	myset.clear();

	set_difference(m_using_epset.begin(), m_using_epset.end(), 
			m_disconnection_epset.begin(), m_disconnection_epset.end(), 
			inserter(myset, myset.begin()));
	m_using_epset.clear();
	m_using_epset = myset;

	reset(fdread, maxfd);
	m_connection_epset.clear();
	m_disconnection_epset.clear();
}

void CEndpointset::gofirstusing()
{
	m_using_li = m_using_epset.begin();
}

bool CEndpointset::getnextusing(CEndpoint &ep)
{
	if(m_using_li !=  m_using_epset.end())
	{
		ep = (*m_using_li);
		m_using_li++;
		return true;
	}
	return false;
}

void  CEndpointset::display()
{
	copy(m_using_epset.begin(), m_using_epset.end(), ostream_iterator<CEndpoint>(cout, "\n"));
}

void CEndpointset::reset(fd_set* fdread, unsigned int* maxfd)
{
	FD_ZERO(fdread);
	ITERATOR LI;
	for(LI = m_using_epset.begin(); LI != m_using_epset.end(); LI++)
	{
		CEndpoint ep = (*LI);
		if (ep.getsocket() > *maxfd)
		{
			*maxfd = ep.getsocket();
		}
		FD_SET(ep.getsocket(), fdread);
	}
}


 

主函数

 

// select.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Endpointset.h"

int _tmain(int argc, _TCHAR* argv[])
{

	WSADATA wsaData;

	WSAStartup(0x0202, &wsaData);

	SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	int ul = 1;
	ioctlsocket(sListen, FIONBIO,(unsigned long *)&ul);

	//Bind
	SOCKADDR_IN local;
	local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	local.sin_family = AF_INET;
	local.sin_port = htons(55555);
	bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));

	// Listen
	listen(sListen, 1);

	fd_set fdread;
	FD_ZERO(&fdread);

	CEndpointset epset;
	CEndpoint ep(sListen, SERVER);
	epset.insertusing(ep);

	FD_SET(sListen, &fdread);
	unsigned int maxfd = sListen;

	while(true)
	{
		int ret = select(maxfd + 1, &fdread, NULL, NULL, 0);
		if (ret > 0)
		{	
			epset.gofirstusing();
			while(epset.getnextusing(ep))
			{
				if (FD_ISSET(ep.getsocket(), &fdread))
				{
					if (ep.gettype() == SERVER)
					{
						
						SOCKADDR_IN client;
						int len = sizeof(client);
						SOCKET sClient = accept(sListen,  (struct sockaddr *)&client, &len);	
						
						if (sClient == INVALID_SOCKET)
						{
							wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
						}

						ioctlsocket(sClient, FIONBIO, (unsigned long *)&ul);

						CEndpoint newep(sClient, CLIENT);
						epset.insertconnection(newep);
					
					}
					else if(ep.gettype() == CLIENT)
					{	
						char buff[256];
						int length = recv(ep.getsocket(), buff, 256, 0);
						if (length <= 0)
						{
							wprintf(L"recv failed with error: %ld\n", WSAGetLastError());
							epset.insertdisconnection(ep);
						}
						else
						{
							printf("length=%d buff=%s\n", length, buff);
						}
					}
				}
			}
			epset.resettle(&fdread, &maxfd);
			printf("socket in using\n");
			epset.display();
			printf("*********************\n");
			printf("socket in fdread\n");
			for(int i=0; i<fdread.fd_count; i++)
			{
				printf("socket=%d\n", fdread.fd_array[i]);
			}
		}
	}
	return 0;
}




 

 

 

 

 

 

抱歉!评论已关闭.