I/O复用 select c/s 网络模型

需求:

使用io复用(select) 实现一个服务器与客户端, 用于模拟用户登录,登出,以及广播消息;

下面代码并没有解决粘包烧包 和解包的问题 , 具体解决方案: tcp 粘包 解包 少包 两种解决方式

 

以下为win32平台, unix平台稍作修改即可运行;

原本想用iocp或者eventselect 实现更为简单,但人说非得要用select,好把.

 

下面代码的发送消息和接受消息都使用了结构, 分2个部分一个消息头一个消息体

用于登录登出,用户加入的头文件,定义消息结构的:

trans.h

enum CMD{
	CMD_LOGIN, //登录 由客户端发送给服务端
	CMD_LOGOUT, //登出
	CMD_LOGIN_RESULT,//登录结果,由服务端发送给客户端
	CMD_LOGOUT_RESULT,//登出结果
	CMD_USER_JOIN, //由服务端群发给客户端
	CMD_ERROR
};

//消息头
typedef struct _DataHeader{
	short dataLen;  //用于定义消息体长度
	short cmd;     //对应上面的命令
} DataHeader, *LPDataHeader;

//登录
typedef struct _Login {
	DataHeader header; //消息头
	char uname[32];  //用户名
	char passwd[32]; //密码
} Login, *LPLogin;

//登录结果
typedef struct _LoginResult{
	DataHeader header;
	short result; //一个示意
}LoginResult, *LPLoginResult;

//登出
typedef struct _Logout{
	DataHeader header;
	char uname[32]; //一个示意
}Logout, *LPLogout;

//登出结果
typedef struct _LogoutResult{
	DataHeader header;
	short result; //示意
}LogoutResult, *LPLogoutResult;

//群发命令
typedef struct _UserJoin{
	DataHeader header;
	int sock;  //占位符,没鸟用
}UserJoin, *LPUserJoin;

 

用于打印错误消息的, 好像没用到,忘了

utils.h

#include <stdlib.h>
#include <TCHAR.h>
#include <stdio.h>
#include <winsock2.h>
#include <Windows.h>
#include <Ws2ipdef.h>
#include <locale.h>
#pragma comment(lib, "ws2_32.lib")
const SIZE_T ERR_MSG_SIZE = 1 << 13;
const unsigned short PORT = 9988;
const int BACKLOG = 20;
void print_error(DWORD err){
	//使用当前平台的字符集
	_tsetlocale(LC_ALL, L"");
	//创建一块内存一直存放错误信息
	static HANDLE g_heap = HeapCreate(0, ERR_MSG_SIZE, 0);
	static TCHAR *buf = (TCHAR*)HeapAlloc(g_heap, 0, ERR_MSG_SIZE);
	//使用当前平台的语言
	DWORD syslocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
	DWORD ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, err, syslocale, buf, ERR_MSG_SIZE, NULL);

	if (!ret){
		//如果上面没找到错误,去网络错误中查找
		static HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
		if (hDll){
			//如果在dll中查找,FORMAT_MESSAGE_FROM_HMODULE 添加上去, 第2个参数填写句柄
			ret = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
				hDll, err, syslocale, buf, ERR_MSG_SIZE, NULL);
		}
	}
	if (ret && buf){
		buf[ret] = 0;
		_tprintf(TEXT("buf:%s\n"), buf);
	}
	else{
		_tprintf(TEXT("unknow error : %ld\n"), err);
	}
}

 

 

正式代码:

serv.cpp



#include "stdafx.h"
#include "../trans.h"  
#define _UNICODE
#define UNICODE

#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
#define BUFSIZE 1024
#define PORT 9988
#define BACKLOG 10

//没用到
int setNonBlockMode(SOCKET sock, u_long bEnable)
{
	return ioctlsocket(sock, FIONBIO, &bEnable);
}

//处理每个客户端传送的数据,maxi 最大索引,cliens 存放socket, readset 有响应的socket
void process_clients(int maxi, SOCKET * clients, FD_SET *readset, FD_SET *allreadset, int *nready);

//广播消息  , sock_arr_index 不想给这个socket发送数据的索引
void boardcast_msg(int cmd, int * sock_arr_index, int maxi = -1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值