服务器端:

#include<WinSock2.h>
#include<Windows.h>
#include<vector>
#include<stdio.h>
#include<iostream> #pragma comment(lib,"ws2_32.lib") enum CMD { CMD_Login, CMD_Login_Result, CMD_Logout, CMD_Logout_Result, CMD_New_User_Join, CMD_ERROR }; //包头
struct DataHeader
{
short dataLength;
short cmd;
};
//包体
struct Login:public DataHeader
{
Login()
{
dataLength = sizeof(Login);
cmd = CMD_Login;
}
char username[];
char password[];
}; struct LoginResult :public DataHeader
{
LoginResult()
{
dataLength = sizeof(LoginResult);
cmd = CMD_Login_Result;
result = ;
}
int result;
}; struct Logout :public DataHeader
{
Logout()
{
dataLength = sizeof(Logout);
cmd = CMD_Logout;
}
char username[];
}; struct LogoutResult :public DataHeader
{
LogoutResult()
{
dataLength = sizeof(LogoutResult);
cmd = CMD_Logout_Result;
result = ;
}
int result;
}; struct NewUserJoin :public DataHeader
{
NewUserJoin()
{
dataLength = sizeof(NewUserJoin);
cmd = CMD_New_User_Join;
sock = ;
}
int sock;
}; std::vector<SOCKET> g_client; int process_solve(SOCKET _cSOCK)
{
//增加一个缓冲区
char szRecv[] = {};
//5.接收客户端新数据
int nLen = recv(_cSOCK, szRecv, sizeof(DataHeader), );
DataHeader *header = (DataHeader*)szRecv; if (nLen <= )
{
printf("客户端已退出!任务结束!");
return -;
}
switch (header->cmd){
case CMD_Login:
{
recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
Login *login = (Login*)szRecv;
printf("收到客户端<Socket=%d>请求:CMD_Login,数据长度:%d\nUserName:%s\nPassWord:%s\n", _cSOCK,login->dataLength, login->username, login->password);
//忽略判断用户密码是否正确的过程
LoginResult ret;
send(_cSOCK, (char *)&ret, sizeof(LoginResult), ); //再发消息体 }
case CMD_Logout:
{ recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
Logout* logout = (Logout*)szRecv;
printf("收到命令:CMD_Logout,数据长度:%d\nUserName:%s\n", logout->dataLength, logout->username); //忽略判断用户密码是否正确的过程
LogoutResult let;
send(_cSOCK, (char *)&let, sizeof(let), ); //再发消息体
}
break;
case CMD_New_User_Join:
{ recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
NewUserJoin* UserJoin = (NewUserJoin*)szRecv;
printf("收到命令:CMD_Logout,数据长度:%d\nUserName:%s\n", UserJoin->dataLength); //忽略判断用户密码是否正确的过程
NewUserJoin let;
send(_cSOCK, (char *)&let, sizeof(let), ); //再发消息体
}
break;
default:
{
DataHeader header = { };
send(_cSOCK, (char *)&header.cmd, sizeof(header), );
} break;
}
} int main()
{ WORD ver = MAKEWORD(, );
WSADATA dat;
//WinSocket启动
WSAStartup(ver, &dat); //1、建立一个socket
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET创建一个IPV4的套接字,SOCK_STREAM面向数据流的,IPPROTO_TCP TCP
if (INVALID_SOCKET == _sock)
{
printf("ERROR:建立失败!\n");
}
//2.绑定
sockaddr_in _sin = {}; //创建网络地址
_sin.sin_family = AF_INET;
_sin.sin_port = htons(); //Host to Network Short
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // IP地址
if (bind(_sock, (sockaddr *)&_sin, sizeof(_sin)) == SOCKET_ERROR)
{
printf("ERROR:绑定失败!\n");
}
else
{
printf("服务器端绑定成功......\n");
}
//3.监听网络端口
if (listen(_sock, ) == SOCKET_ERROR)//第二个参数为最大等待多少人可以同时连接
{
printf("ERROR:监听失败!\n");
}
else
{
printf("服务器端监听成功......\n");
} while ()
{
//伯克利 socket
fd_set fd_Read;
fd_set fd_Write;
fd_set fd_Exp; FD_ZERO(&fd_Read);//FD_ZERO 清空集合里的数据
FD_ZERO(&fd_Write);
FD_ZERO(&fd_Exp); FD_SET(_sock, &fd_Read);//FD_SET 可以进行操作的宏
FD_SET(_sock, &fd_Write);
FD_SET(_sock, &fd_Exp); for (int n = g_client.size() - ; n >= ; n--)
{
FD_SET(g_client[n], &fd_Read);
} /*
select(
_In_ int nfds,
_Inout_opt_ fd_set FAR * readfds,
_Inout_opt_ fd_set FAR * writefds,
_Inout_opt_ fd_set FAR * exceptfds,
_In_opt_ const struct timeval FAR * timeout
);
*/ //nfds是一个整数值,是指fd_set集合所有的描述符(select里的第一个参数)的范围(而不是数量)
//既是所有文件描述符最大值+1
timeval t = {,}; int ret = select(_sock + , &fd_Read, &fd_Write, &fd_Exp, &t);
if (ret < )
{
printf("select任务结束!\n");
break;
}
if (FD_ISSET(_sock, &fd_Read))
{
FD_CLR(_sock, &fd_Read);
//4.等待接收客户端连接
sockaddr_in clientAddr = {};
int nAddrLen = sizeof(sockaddr_in);
SOCKET _cSOCK = INVALID_SOCKET; _cSOCK = accept(_sock, (sockaddr *)&clientAddr, &nAddrLen);
if (_cSOCK == INVALID_SOCKET)
{
printf("ERROR:无效客户端SOCKET!\n");
}
for (int n = g_client.size() - ; n >= ; n--)
{
NewUserJoin UserJoin;
send(g_client[n], (const char*)&UserJoin, sizeof(UserJoin), );
} g_client.push_back(_cSOCK);
printf("新客户端加入:Socket=%d,IP = %s\n", (int)_cSOCK, inet_ntoa(clientAddr.sin_addr));//inet_ntoa(clientAddr.sin_addr)将接收到的IP地址转化为字符串 }
for (int n = ; n < fd_Read.fd_count; n++)
{
if (process_solve(fd_Read.fd_array[n]) == -)
{
auto iter = find(g_client.begin(), g_client.end(), process_solve(fd_Read.fd_array[n]));
if (iter != g_client.end())
{
g_client.erase(iter);
}
}
}
printf("空闲时间处理其他业务.......\n");
} for (int n = g_client.size(); n >= ; n--)
{
//8.关闭自身的socket
closesocket(g_client[n]);
} //8.关闭自身的socket
closesocket(_sock); //WinSocket关闭
WSACleanup(); system("pause");
return ;
}

客户端:

#include<WinSock2.h>
#include<Windows.h>
#include<stdio.h> #pragma comment(lib,"ws2_32.lib") enum CMD { CMD_Login, CMD_Login_Result, CMD_Logout, CMD_Logout_Result, CMD_New_User_Join, CMD_ERROR }; //包头
struct DataHeader
{
short dataLength;
short cmd;
};
//包体
struct Login :public DataHeader
{
Login()
{
dataLength = sizeof(Login);
cmd = CMD_Login;
}
char username[];
char password[];
}; struct LoginResult :public DataHeader
{
LoginResult()
{
dataLength = sizeof(LoginResult);
cmd = CMD_Login_Result;
result = ;
}
int result;
}; struct Logout :public DataHeader
{
Logout()
{
dataLength = sizeof(Logout);
cmd = CMD_Logout;
}
char username[];
}; struct LogoutResult :public DataHeader
{
LogoutResult()
{
dataLength = sizeof(LogoutResult);
cmd = CMD_Logout_Result;
result = ;
}
int result;
}; struct NewUserJoin :public DataHeader
{
NewUserJoin()
{
dataLength = sizeof(LogoutResult);
cmd = CMD_New_User_Join;
sock = ;
}
int sock;
}; int process_solve(SOCKET _cSOCK)
{
//增加一个缓冲区
char szRecv[] = {};
//5.接收客户端新数据
int nLen = recv(_cSOCK, szRecv, sizeof(DataHeader), );
DataHeader *header = (DataHeader*)szRecv; if (nLen <= )
{
printf("与服务器断开连接!任务结束!");
return -;
}
switch (header->cmd){
case CMD_Login_Result:
{
recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
LoginResult *loginresult = (LoginResult*)szRecv;
printf("收到服务端消息请求:CMD_Login_Result,数据长度:%d\nUserName:%s\nPassWord:%s\n", loginresult->dataLength); }
break;
case CMD_Logout_Result:
{ recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
LogoutResult* logoutresult = (LogoutResult*)szRecv;
printf("收到服务端消息请求:CMD_Logout_Result,数据长度:%d\nUserName:%s\n", logoutresult->dataLength); }
break;
case CMD_New_User_Join:
{
recv(_cSOCK, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), );
NewUserJoin* newuserjoin = (NewUserJoin*)szRecv;
printf("收到服务端消息请求:CMD_New_User_Join,数据长度:%d\nUserName:%s\n", newuserjoin->dataLength);
}
break;
}
} int main()
{
WORD ver = MAKEWORD(, );
WSADATA dat;
WSAStartup(ver, &dat); //1.建立一个socket
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == _sock)
{
printf("ERROR:建立失败!\n");
}
else{
printf("客户端绑定成功......\n");
}
//2.连接服务器
sockaddr_in _sin = {}; //创建网络地址
_sin.sin_family = AF_INET;
_sin.sin_port = htons(); //Host to Network Short
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//inet_addr("127.0.0.1"); // IP地址
int ret = connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
if (SOCKET_ERROR == ret)
{
printf("ERROR:连接失败!\n");
}
else
{
printf("客户端连接成功......\n");
} while (true)
{
//伯克利 socket
fd_set fd_Read;
FD_ZERO(&fd_Read);//FD_ZERO 清空集合里的数据
FD_SET(_sock, &fd_Read);//FD_SET 可以进行操作的宏
timeval t = {,};
int ret = select(_sock, &fd_Read, , ,&t);
if (ret < )
{
printf("select任务结束1!");
break;
}
if (FD_ISSET(_sock,&fd_Read))
{
FD_CLR(_sock, &fd_Read); if (process_solve(_sock) == -)
{
printf("select任务结束2!");
break;
}
}
printf("空闲时间处理其他业务.......\n");
Login login;
strcpy(login.username, "sutaoyu");
strcpy(login.password, "sutaoyu01");
send(_sock, (const char*)&login, sizeof(Login),);
Sleep();
} //7.关闭套接字
closesocket(_sock); //WinSocket启动
WSAStartup(ver, &dat); //WinSocket关闭
WSACleanup();
printf("已退出!");
getchar();
return ;
}

客户端升级为select网路模型的更多相关文章

  1. mac系统及xcode使用的SVN客户端升级

    mac系统及xcode使用的SVN客户端升级 当前的SVN版本已经升级到1.8.x了,但mac系统自带的以及xcode使用的SVN客户端版本没有跟着升级,还是1.6.x的版本.为了解决隐藏目录.svn ...

  2. 【HANA系列】SAP HANA STUDIO客户端升级更新

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA STUDIO客 ...

  3. 服务器端升级为select模型处理多客户端

    流程图: select会定时的查询socket查询有没有新的网络连接,有没有新的数据需要读,有没有新的请求需要处理,一旦有新的数据需要处理,select就会返回,然后我们就可以处理相应的数据,sele ...

  4. 【转】你真的懂select Socket模型吗?

    转自:http://www.cppblog.com/xvsdf100/archive/2013/12/10/204689.html     只要接触过c/c++网路编程人都可能会知道select io ...

  5. windows下的IO模型之选择(select)模型

    1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作. 选择模型的核心是FD_SET集合和select函数.通过该函数,我们可以 ...

  6. 微信iOS客户端升级内核对自定义分享的影响

    上周,业务同学反应,公司的商品详情页,在有的Iphone手机上自定义分享信息失效.在自己手机上一直无法重现,在一个同事的手机上也重现了. 后来看到<微信iOS客户端将升级为WKWebview内核 ...

  7. select服务器端模型封装——回调方式快速建立服务端

    #pragma once #ifndef WINSOCK2_H #define _WINSOCK_DEPRECATED_NO_WARNINGS #include<WinSock2.h> # ...

  8. mongo客户端升级导致pymongo中使用聚合函数时出现异常

    一.异常信息 The 'cursor' option is required, except for aggregate with the explain argument 二.解决办法 #部分源代码 ...

  9. 异步套接字编程之select模型

      █ 选择(select)模型是Winsock中最常见的 I/O模型.核心便是利用 select 函数,实现对 I/O的管理!利用 select 函数来判断某Socket上是否有数据可读,或者能否向 ...

随机推荐

  1. hibernate 第二次深入接触

    1.session 到底如何进行脏处理? 当一个Dept对象加入到session缓存时,Session会为Dept对象的值属性复制一份快照,当Session刷新缓存时,会进行脏处理. 2.OID 用来 ...

  2. jmeter解决乱码

    在jmeter.properties 这个文件里面 找到sampleresult.default.encoding=xx 后面xx改成utf-8,然后取消注释 解决jmeterbody里面中文显示不出 ...

  3. AbstractQueuedSynchronizer 源码解读(转载)

    转载文章,拜读了一下原文感觉很不错,转载一下,侵删 链接地址:http://objcoding.com/2019/05/05/aqs-exclusive-lock/ Java并发之AQS源码分析(一) ...

  4. hi cnblogs

    hi cnblogs 前言: 作为一个工作好些年的it男,还没正经写过技术博客,真是太羞愧了... 正文: 先扯点儿虚的,无论从事什么行业,最重要的都是自我认知和自我定位.至今,我也有工作了小五年了, ...

  5. 带你手写基于 Spring 的可插拔式 RPC 框架(四)代理类的注入与服务启动

    上一章节我们已经实现了从客户端往服务端发送数据并且通过反射方法调用服务端的实现类最后返回给客户端的底层协议. 这一章节我们来实现客户端代理类的注入. 承接上一章,我们实现了多个底层协议,procoto ...

  6. nginx 转发tcp连接

    背景:公司有一套工作流服务(jira,confluence,bitbucket),目前jira,confluence配置的是从nginx网关进行转发,bitbucket配置的是直接解析到该主机,现在计 ...

  7. #【Python】【demo实验34】【练习实例】【设置文本的颜色】

    原题: 文本颜色设置. 我的代码 #!/usr/bin/python # encoding=utf-8 # -*- coding: UTF-8 -*- # 文本颜色设置. class bcolors: ...

  8. Redis-负载均衡

    摘要 在nginx里面配置一个upstream,然后把相关的服务器ip都配置进去.然后采用轮询的方案,然后在nginx里面的配置项里,proxy-pass指向这个upstream,这样就能实现负载均衡 ...

  9. [翻译] 深入浅出Go语言调度器:第一部分 - 系统调度器

    目录 译者序 序 介绍 系统调度器 执行指令 Figure 1 Listing 1 Listing 2 Listing 3 线程状态 任务侧重 上下文切换 少即是多 寻找平衡 缓存行 Figure 2 ...

  10. 剑指offer38:输入一棵二叉树,求该树的深度

    1 题目描述 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 2 思路和方法 深度优先搜索,每次得到左右子树当前最大路径,选择 ...