socket 的select函数例子
2015-09-18 16:20
309 查看
好久没有写博客了,主要最近也没有学啥新的可以写博客的东西
select函数是通过设置FD_SET来实现在一个线程中实现读写网口的,下面这段代码主要是实现绑定端口-》监听-》设置socket为非阻塞-》读取网口-》回写网口的。缺点是只能有一个socket连接,优点是代码简单,便于入门。在这里鄙视一下 《socket编程之select()》的博主,写个代码还故意整点bug,不过他写的文字还是很好的,可以配合下面的代码看看,不过代码不是他的哦。
#include <WINSOCK2.H>
#include <iostream>
#pragma comment(lib,"WS2_32.lib")
#define PORT 8080
#define DATA_BUFSIZE 8192
char recvBuffer[DATA_BUFSIZE];
//目标是一个客户端可以连接
int main()
{
SOCKET ListenSocket; // 监听套接字
SOCKET AcceptSocket; // 与客户端进行通信的套接字
SOCKADDR_IN InternetAddr; // 服务器的地址
WSADATA wsaData; // 用于初始化套接字环境
INT Ret; // WinSock API的返回值
FD_SET WriteSet; // 获取可写性的套接字集合
FD_SET ReadSet; // 获取可读性的套接字集合
DWORD Total = 0; // 处于就绪状态的套接字数量
DWORD SendBytes; // 发送的字节数
DWORD RecvBytes; // 接收的字节数
bool bSocketInit = false;//socket是否初始化过
// 初始化WinSock环境
if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
{
printf("WSAStartup() failed with error %d\n", Ret);
WSACleanup();
return -1;
}
ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
//绑定
if(bind(ListenSocket, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return -1;
}
//监听
listen(ListenSocket,1);
//设置费阻塞
u_long noneBlock = 1 ;
ioctlsocket(ListenSocket,FIONBIO,&noneBlock);
int recvLen = 0;
while(true)
{
//清空
FD_ZERO(&ReadSet);
FD_ZERO(&WriteSet);
//指定listensocket可以读
FD_SET(ListenSocket,&ReadSet);
if(bSocketInit)
{
FD_SET(AcceptSocket,&ReadSet);//注意,就只能连接一个,因为这样代码简单
FD_SET(AcceptSocket,&WriteSet);
}
//循环调用select函数
select(1,&ReadSet,&WriteSet,NULL,NULL);//不检测错误信息,不阻塞
//判断有没有新的socket连接
if(FD_ISSET(ListenSocket,&ReadSet))
{
AcceptSocket = accept(ListenSocket,NULL,NULL);
//设置新来的socket为非阻塞
ioctlsocket(AcceptSocket,FIONBIO,&noneBlock);
bSocketInit = true;//就能连接一个
}
//判断新的socket
if(bSocketInit)
{
if(FD_ISSET(AcceptSocket,&ReadSet)){
//接受数据
int len = recv(AcceptSocket,recvBuffer,DATA_BUFSIZE,0);
if(len>0){
recvLen = len;
}else{
//客户端关闭了
bSocketInit = false;
closesocket(AcceptSocket);
len = 0;
recvLen = 0;
}
}
if(FD_ISSET(AcceptSocket,&WriteSet))
{
//
if(recvLen>0)
{
if( send(AcceptSocket,recvBuffer,recvLen,0)
!= SOCKET_ERROR)
{
recvLen = 0;
printf(recvBuffer);
}
}
}
}
}
}
select函数是通过设置FD_SET来实现在一个线程中实现读写网口的,下面这段代码主要是实现绑定端口-》监听-》设置socket为非阻塞-》读取网口-》回写网口的。缺点是只能有一个socket连接,优点是代码简单,便于入门。在这里鄙视一下 《socket编程之select()》的博主,写个代码还故意整点bug,不过他写的文字还是很好的,可以配合下面的代码看看,不过代码不是他的哦。
#include <WINSOCK2.H>
#include <iostream>
#pragma comment(lib,"WS2_32.lib")
#define PORT 8080
#define DATA_BUFSIZE 8192
char recvBuffer[DATA_BUFSIZE];
//目标是一个客户端可以连接
int main()
{
SOCKET ListenSocket; // 监听套接字
SOCKET AcceptSocket; // 与客户端进行通信的套接字
SOCKADDR_IN InternetAddr; // 服务器的地址
WSADATA wsaData; // 用于初始化套接字环境
INT Ret; // WinSock API的返回值
FD_SET WriteSet; // 获取可写性的套接字集合
FD_SET ReadSet; // 获取可读性的套接字集合
DWORD Total = 0; // 处于就绪状态的套接字数量
DWORD SendBytes; // 发送的字节数
DWORD RecvBytes; // 接收的字节数
bool bSocketInit = false;//socket是否初始化过
// 初始化WinSock环境
if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
{
printf("WSAStartup() failed with error %d\n", Ret);
WSACleanup();
return -1;
}
ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
//绑定
if(bind(ListenSocket, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return -1;
}
//监听
listen(ListenSocket,1);
//设置费阻塞
u_long noneBlock = 1 ;
ioctlsocket(ListenSocket,FIONBIO,&noneBlock);
int recvLen = 0;
while(true)
{
//清空
FD_ZERO(&ReadSet);
FD_ZERO(&WriteSet);
//指定listensocket可以读
FD_SET(ListenSocket,&ReadSet);
if(bSocketInit)
{
FD_SET(AcceptSocket,&ReadSet);//注意,就只能连接一个,因为这样代码简单
FD_SET(AcceptSocket,&WriteSet);
}
//循环调用select函数
select(1,&ReadSet,&WriteSet,NULL,NULL);//不检测错误信息,不阻塞
//判断有没有新的socket连接
if(FD_ISSET(ListenSocket,&ReadSet))
{
AcceptSocket = accept(ListenSocket,NULL,NULL);
//设置新来的socket为非阻塞
ioctlsocket(AcceptSocket,FIONBIO,&noneBlock);
bSocketInit = true;//就能连接一个
}
//判断新的socket
if(bSocketInit)
{
if(FD_ISSET(AcceptSocket,&ReadSet)){
//接受数据
int len = recv(AcceptSocket,recvBuffer,DATA_BUFSIZE,0);
if(len>0){
recvLen = len;
}else{
//客户端关闭了
bSocketInit = false;
closesocket(AcceptSocket);
len = 0;
recvLen = 0;
}
}
if(FD_ISSET(AcceptSocket,&WriteSet))
{
//
if(recvLen>0)
{
if( send(AcceptSocket,recvBuffer,recvLen,0)
!= SOCKET_ERROR)
{
recvLen = 0;
printf(recvBuffer);
}
}
}
}
}
}
相关文章推荐
- python多线程编程:生成者和消费者
- android系统平台显示驱动开发简要:LCD驱动调试篇『四』
- Cocos2d-js v3.1 事件分发机制
- 经常用到的代码段
- 算法之每日一题:找出无序数组中第k大的数字
- opengl函数功能详解
- java生成范围内的纯数字随机数
- Effective C++——条款45(第7章)
- HTML+CSS 学习清单
- Perl 调用BTEQ
- IOS编译报错:objc-class-ref in AppDelegate.o之解决方案 Xcode7
- 黑马程序员_java面向对象_抽象类和接口
- Activity启动模式图文详解:standard, singleTop, singleTask 以及 singleInstance
- centos7 install 安装mysql
- 概念性知识与程序性知识的关系
- c++ 抽象概念,内存格局,浅拷贝,深拷贝,临时对象,无名对象
- 工作周报060
- Nagios显示类似错误:HTTP WARNING: HTTP/1.1 403 Forbidden - 5240 bytes in 0.002 second response time。
- 使用SecureCRT设置linux系统登录的ssh公钥认证
- Linux中的STDIN_FILENO和STDOUT_FILENO