C++socket客户端select异步连接发送接收数据

简介: C++socket客户端select异步连接发送接收数据

这段时间公司项目一直用网口同底层设备交互,顾记录下,具体见代码:

int RFID_STANDARDPROTOCOL_API __stdcall Socket_SendAndRecv(SOCKET Socket, unsigned char * SendBuf
                                                       , unsigned char *RecvBuf, int send_len)
{
    int check_len = send_len - 1;
  int index;
  SendBuf[check_len] = 0;
  for(index = 0; index < check_len; index++)
  {
    SendBuf[check_len] += SendBuf[index];
  }
  SendBuf[check_len] = ~SendBuf[check_len] + 1;
  char recvbuf[1024]={0};
  fd_set fds;
  FD_ZERO(&fds);
  FD_SET(Socket, &fds);
  timeval time_out = {0, 0};
  switch(select(Socket + 1, &fds, NULL, NULL, &time_out))
  {
  case SOCKET_ERROR:
    break;
  case 0:
    break;
  default:
    {
      if (FD_ISSET(Socket, &fds))
      {
        recv(Socket, (char *)recvbuf, 1024, 0);
      }
    }
    break;
  }
  char *sendbuf = (char *)SendBuf;//将 unsigned char* 类型的 SendBuf 强制转换为 char* 类型的 SendBuf
  if(send(Socket, sendbuf, send_len, 0) <= 0)
    return SENDERROR;
  int Lenth = 0;
  HANDLE hEventExit = NULL;
  WSAEVENT EventArray[2] = {WSACreateEvent(), hEventExit};
  WSAEventSelect(Socket, EventArray[0], FD_READ);
  DWORD dwWait = WSAWaitForMultipleEvents(1, EventArray, FALSE, 1000, FALSE);
  if (WAIT_OBJECT_0 == dwWait)
  {
    WSANETWORKEVENTS netEvents;
    if (SOCKET_ERROR == WSAEnumNetworkEvents(Socket, EventArray[0], &netEvents))
    {
      return -1;
    }
    if (!(netEvents.lNetworkEvents & FD_READ) || netEvents.iErrorCode[FD_READ_BIT])
    {
      return -1;
    }
    if((Lenth=recv(Socket, recvbuf, sizeof(recvbuf)-1, 0))<=0)
      return RECVERROR;
  }
  for(index = 0; index < Lenth; index++)
  {
    RecvBuf[index] = (unsigned char)recvbuf[index]; //将 char 类型的 RecvBuf 强制转换为 unsigned  char 类型的 RecvBuf
  }
  if((RecvBuf[0] == 0x0B) && (RecvBuf[3] == 0))
    return SUCCESS;
  else
    return DATAERROR;
}
int RFID_STANDARDPROTOCOL_API __stdcall Socket_ConnectSocket(SOCKET *Socket, char *IPAddress, int Port)
{
    //加载套接字库
  WORD wVersionRequested;
  WSADATA wsaData;
  wVersionRequested = MAKEWORD(1, 1);
  if(WSAStartup(wVersionRequested, &wsaData) != 0)
  {
    return -1;
  }
  if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  {
    WSACleanup();
    return -1;
  }
  //创建套接字
  *Socket = socket(AF_INET, SOCK_STREAM, 0);
  if (*Socket == INVALID_SOCKET)
  {
    WSACleanup();
    return -3;
  }
  int TimeOut = 1000;     //设置发送超时2秒
  if(::setsockopt(*Socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
  {
  }
  TimeOut = 1000;     //设置接收超时2秒
  if(::setsockopt(*Socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
  {
  }
  SOCKADDR_IN addrSrv;
  addrSrv.sin_addr.S_un.S_addr = inet_addr(IPAddress);
  addrSrv.sin_family = AF_INET;
  addrSrv.sin_port = htons(Port);
  //向服务器发送连接请求
#define __NONE_BLOCK_CONN__
  /* 非阻塞式连接 */
#ifdef __NONE_BLOCK_CONN__
  unsigned long mode = 1;
  int iRet = ioctlsocket(*Socket, FIONBIO, &mode);
  if (iRet != NO_ERROR)
  {
  }
  int conn_ret = connect(*Socket, (sockaddr *)&addrSrv, sizeof (sockaddr) );
  mode = 0;
  iRet = ioctlsocket(*Socket, FIONBIO, &mode);
  if (iRet != NO_ERROR)
  {
  }
  TIMEVAL timeval = {0};
  timeval.tv_sec = 0;
  timeval.tv_usec = 950 * 1000;
  fd_set Write, Err;
  FD_ZERO(&Write);
  FD_ZERO(&Err);
  FD_SET(*Socket, &Write);
  FD_SET(*Socket, &Err);
  select(*Socket + 1, NULL, &Write, &Err, &timeval);
  if(FD_ISSET(*Socket, &Write))
  {
    return SUCCESS;
  }
    // /* 阻塞式连接 */
#else
  if (connect(*Socket, (sockaddr *)&addrSrv, sizeof (SOCKADDR_IN) ) == 0)
  {
    return SUCCESS;
  }
#endif
  else
  {
    closesocket(*Socket);
    WSACleanup();
    return -2;
  }
}
相关文章
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
339 0
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
9月前
|
监控 API 开发工具
Socket.IO介绍,以及怎么连接测试Socket.IO接口?
Socket.IO 是一个用于浏览器和服务器间实时双向通信的库,支持低延迟消息传递、跨平台运行及自动重连。文章介绍了其特点与调试需求,并详细说明如何使用 Apifox 工具创建、连接、发送/接收 Socket.IO 事件,以及团队协作和调试技巧。掌握这些技能可提升实时应用开发效率与质量。
|
网络协议 数据格式 Python
python Socket无限发送接收数据方式
Socket是指套接字,是对网络中不同主机上的应用进程之间进行双向通信的端点的一种抽象。 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。
|
关系型数据库 MySQL 数据库
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
1299 0
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送&quot;Hello, Server!&quot;后关闭。注意Android中需避免主线程进行网络操作。
306 4
|
Dart API C语言
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
|
网络协议 Java
如何在Java中使用Socket编程实现TCP连接?
在Java中,通过Socket编程实现TCP连接非常常见。以下演示了基本的TCP通信流程,可根据具体需求进行扩展。
685 0
|
网络协议
逆向学习网络篇:通过Socket建立连接并传输数据
逆向学习网络篇:通过Socket建立连接并传输数据
302 0
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
157 0