一、select函数
select()
可以阻塞地同时探测一组支持非阻塞的 I / O 设备是否有事件发生(如可读,可写,出现异常等等),直至某一个设备触发了事件或者超过了指定的等待时间。此时我们可以把需要的数据源通道放到 select 的探测范围内,只要相应的数据源准备好 select 就会返回,这时就能无阻塞地读取到数据。
select()函数原型及介绍如下所示
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout);
二、客户端代码实例
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "mysocket.h"
char pdevMsg[]="i am imx6ull\r\n";
static int sockfd;//socket对象
#define SERVER_PORT 8080 //服务器的端口号
#define SERVER_IP "192.168.1.105" //服务器的 IP 地址
#define BUFF_SIZE 4096
char sock_buff[BUFF_SIZE+1];
uint32_t num=0;
//发送网络线程
static void Send_TO_Server_thread_entry(void *param)
{
while (1)
{
sleep(1);
if(sockfd>0)
{
printf("send data to server...=%d\r\n",num++);
send(sockfd, pdevMsg, sizeof pdevMsg, 0);
}
}
}
static void* SocketManageThread(void* parameter)
{
int count = 0;
int no = (int) parameter; /* 获得线程的入口参数 */
struct sockaddr_in server_addr = {0};
char buf[512];
int ret;
/* 打开套接字,得到套接字描述符 */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (0 > sockfd)
{
perror("socket error");
exit(EXIT_FAILURE);
}
/* 调用 connect 连接远端服务器 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT); //端口号
inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);//IP 地址
//连接服务器
while(1)
{
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(sockfd>0)
{
//tip
send(sockfd, pdevMsg, sizeof pdevMsg, 0);
printf("服务器连接成功...\r\n");
break;
}
sleep(2);
printf("正在连接服务器...\r\n");
}
fd_set fds;
int32_t max_fd = 0, res = 0;
max_fd = sockfd + 1;
FD_ZERO(&fds);
while (1)
{
/* 将需要监听可读事件的描述符加入列表 */
FD_SET(sockfd, &fds);
/* 等待设定的网络描述符有事件发生 */
printf("wai server data to come...\r\n");
res = select(max_fd, &fds, NULL, NULL, NULL);//阻塞等待网络数据到来
/* 查看 sock 描述符上有没有发生可读事件 */
if (FD_ISSET(sockfd, &fds))
{
//网络数据接收
/* 从 sock 连接中接收最大BUFSZ - 1字节数据 */
res = recv(sockfd, sock_buff, BUFF_SIZE, 0);
if(res>0)
{
//处理网络数据
sock_buff[res]="\0";
printf("%s",sock_buff);
}
}
//pipe管道,发送数据,后续添加...
}
}
int mysocketInit(void)
{
int result,result1;
pthread_t tid,tid1;
result = pthread_create(&tid,NULL,SocketManageThread,(void*)4);
//网络发送线程
result1 = pthread_create(&tid,NULL,Send_TO_Server_thread_entry,(void*)5);
printf("Create network communication task\r\n");
}