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;
  }
}
相关文章
|
4月前
|
消息中间件 存储 开发工具
消息队列 MQ产品使用合集之C++如何使用Paho MQTT库进行连接、发布和订阅消息
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
9天前
|
关系型数据库 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’
34 0
|
2月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
69 0
|
3月前
|
网络协议 Java
如何在Java中使用Socket编程实现TCP连接?
在Java中,通过Socket编程实现TCP连接非常常见。以下演示了基本的TCP通信流程,可根据具体需求进行扩展。
124 0
|
4月前
|
Java Android开发
Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。
【6月更文挑战第23天】 Java Socket编程示例:服务器开启在8080端口监听,接收客户端连接并打印消息。客户端连接服务器,发送&quot;Hello, Server!&quot;后关闭。注意Android中需避免主线程进行网络操作。
74 4
|
3月前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
42 0
|
4月前
|
Java
java使用ServerSocket和Socket实现客户端与服务端通讯
java使用ServerSocket和Socket实现客户端与服务端通讯
|
4月前
|
网络协议
逆向学习网络篇:通过Socket建立连接并传输数据
逆向学习网络篇:通过Socket建立连接并传输数据
43 0
|
4月前
|
网络协议 Java Linux
探索Java Socket编程:实现跨平台客户端-服务器通信的奥秘
【6月更文挑战第21天】Java Socket编程示例展示了如何构建跨平台聊天应用。服务器端使用`ServerSocket`监听客户端连接,每个连接启动新线程处理。客户端连接服务器,发送并接收消息。Java的跨平台能力确保代码在不同操作系统上无需修改即可运行,简化开发与维护。
47 0
|
3月前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
33 4