select i/o + 多线程 实现多个客户连接

// select_selfDlg.h : 头文件
//

#pragma once
#include "CInitSock.h"

#include <list>
#include "afxwin.h"
using namespace std;
#define		THREAD_NUM		2

// Cselect_selfDlg 对话框
class Cselect_selfDlg : public CDialog
{
// 构造
public:
	Cselect_selfDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_SELECT_SELF_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
	
	static DWORD WINAPI ListenThreadFun(LPVOID lpParam); 
	static DWORD WINAPI ClientThreadFun(LPVOID lpParam);
	HANDLE handleArray[THREAD_NUM];

	void showMessage(CString & szinfo);
	CInitSock m_InitSock;
	SOCKET m_sockListen;
	HANDLE handleEvent;

	list<SOCKET> m_vecSockClient;


// 实现

protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButton1();
	afx_msg void OnClose();
	CEdit m_Edit;
};

以下是主要几个线程函数

void Cselect_selfDlg::OnBnClickedButton1()
{
	handleEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	handleArray[0] = CreateThread(NULL,0,ListenThreadFun,this,NULL,NULL);
	handleArray[1] = CreateThread(NULL,0,ClientThreadFun,this,NULL,NULL);
}

DWORD WINAPI Cselect_selfDlg::ListenThreadFun(LPVOID lpParam)
{
	Cselect_selfDlg * pThis = (Cselect_selfDlg *)lpParam;
	pThis->m_sockListen = socket(AF_INET,SOCK_STREAM,0);

	if(pThis->m_sockListen == INVALID_SOCKET)
	{
		AfxMessageBox(_T("创建套接字失败!"));
		return 0;
	}
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(4567);
	sin.sin_addr.S_un.S_addr = INADDR_ANY;

	bind(pThis->m_sockListen,(sockaddr*)&sin,sizeof(sin));
	listen(pThis->m_sockListen,5);

	while(TRUE)
	{
		//WaitForSingleObject(pThis->handleEvent,INFINITE);
		
		sockaddr_in addRemote;
		int nLen = sizeof(addRemote);
		SOCKET sockaccept = INVALID_SOCKET;
		
		sockaccept = accept(pThis->m_sockListen,(sockaddr*)&addRemote,&nLen);

		if(sockaccept == INVALID_SOCKET)
			continue;
		
		CString szIpInfo = Multi2WideChar(inet_ntoa(addRemote.sin_addr));
		pThis->showMessage(szIpInfo);
// 		if(pThis->m_vecSockClient.size() > 64)
// 		{
// 			send(*sockaccept,"too much client",20,0);
// 			closesocket(*sockaccept);
// 			delete sockaccept;
// 			continue;
// 		}
		pThis->m_vecSockClient.push_back(sockaccept);
	//	SetEvent(pThis->handleEvent);
	}
	
	return 0;
}

DWORD WINAPI Cselect_selfDlg::ClientThreadFun(LPVOID lpParam)
{
	Cselect_selfDlg * pThis = (Cselect_selfDlg*)lpParam;
	fd_set fdset;
	
	while(TRUE)
	{
		//WaitForSingleObject(pThis->handleEvent,INFINITE);
		Sleep(100);
		FD_ZERO(&fdset);
		if(pThis->m_vecSockClient.empty())
			continue;
		list<SOCKET>::iterator iter;
		for(iter = pThis->m_vecSockClient.begin(); iter != pThis->m_vecSockClient.end(); ++ iter)
		{
			FD_SET(*iter,&fdset);
		}
		timeval tv = {1,0};
		int nRet = select(0,&fdset,NULL,NULL,&tv);
		if(nRet > 0)
		{
			//for(int i = 0; i < pThis->m_vecSockClient.size(); i ++)
			for(iter = pThis->m_vecSockClient.begin();iter != pThis->m_vecSockClient.end();)
			{
				if(FD_ISSET(*iter,&fdset))
				{
					TCHAR szBuf[200] = {0};
					int nRev = recv(*iter,(char*)szBuf,200,0);

					if(nRev > 0)
					{
						CString strtemp = szBuf;
						pThis->showMessage(strtemp);
						iter++;
					}
					else
					{
						closesocket(*iter);
						FD_CLR(*iter,&fdset);
						//delete *iter;
						iter = pThis->m_vecSockClient.erase(iter);
						
					}
				}
				else
					iter ++;
			}
		}

	}
	return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目简介: 采用I/O复用技术select实现socket通信,采用多线程负责每个客户操作处理,完成Linux下的多客户聊天室! OS:Ubuntu 15.04 IDE:vim gcc make DB:Sqlite 3 Time:2015-12-09 ~ 2012-12-21 项目功能架构: 1. 采用client/server结构; 2. 给出客户操作主界面(注册、登录、帮助和退出)、登录后主界面(查看在线列表、私聊、群聊、查看聊天记录、退出); 3. 多客户可同时连接服务器进行自己操作; ##服务器端## 1. server.c:服务器端主程序代码文件; 2. config.h:服务器端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:服务器端公共函数的实现文件; 4. list.c:链表实现文件,用于维护在线用户链表的添加、更新、删除操作; 5. register.c:服务器端实现用户注册; 6. login.c:服务器端实现用户登录; 7. chat.c:服务器端实现用户的聊天互动操作; 8. Makefile:服务器端make文件,控制台执行make命令可直接生成可执行文件server ##客户端## 1. client.c:客户端主程序代码文件; 2. config.h:客户端配置文件(包含需要的头文件、常量、数据结构及函数声明); 3. config.c:客户端公共函数的实现文件; 4. register.c:客户实现用户注册; 5. login.c:客户实现用户登录; 6. chat.c:客户实现用户的聊天互动操作; 7. Makefile:客户端make文件,控制台执行make命令可直接生成可执行文件client;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值