【树莓派3B+测评】TCP客户端&阻塞线程创建&取消


【树莓派3B+测评】TCP客户端&阻塞线程创建&取消

在Linux系统中,TCP通信还有一个常用角色是客户端,像树莓派这种板子,经常充当从机角色连接电脑主机,在这种情况下,以客户端身份连接主机是比较易于理解且占用资源较少的做法,主机的服务器一直开着,树莓派从机可按需分时进行TCP连接或者一直检测主机服务器是否掉线以确保通信的稳定,那么,在上一帖中提到过,TCP通信要同时收发且互不干扰,必须开启多一个用于发送的线程,当TCP连接断开的时候,这个线程要挂起或者取消,在频繁的客户端连接主机的过程中,自然也就会频繁地开启或关闭TCP发送线程,这就涉及到线程里面最简单的创建和取消操作。

首先让树莓派以客户端身份连接电脑主机TCP服务器,非常简单,只需要用到socket()和connect()两个函数:

socklen_t addrsize=sizeof(struct sockaddr);
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr)); // 清零
girladdr.sin_family=AF_INET;
girladdr.sin_port=htons(10086); //host-->network
girladdr.sin_addr.s_addr=inet_addr("169.254.122.1");
connect(fd_socket,(struct sockaddr *)&girladdr,addrsize);

如果是做一个循环检测主机TCP服务器是否存在的算法,就使用三个while循环即可:

while(1)
{
while(1)
{
fd_socket=socket(AF_INET,SOCK_STREAM,0);
if(fd_socket==-1)
{
printf("套接字初始化失败!\n");
return -1;
}
ret=connect(fd_socket,(struct sockaddr *)&girladdr,addrsize);
if(ret==0)
{
printf("与服务器建立连接\n");
break;
}
}
while(1)
{
bzero(recvbuf,100);
ret=recv(fd_socket,recvbuf,100,0);
if(ret==0)
{
printf("与服务器失去连接\n");
break;
}
printf("服务器端发来信息:%s\n",recvbuf);
}
}

另外,还要开辟一个用于TCP输入字符串发送的线程,与上一帖一样:

int fd_socket;
pthread_t id1;
unsigned char sendbuf[100],recvbuf[100];
void *Thread_Send_buf(void *arg)
{
int len;
while(1)
{
bzero(sendbuf,100);
scanf("%s",sendbuf);
//printf("----\n");
for(len=0;sendbuf[len]!='\0';len++);
//printf("%d\n",Raspi_DHT11_Read());
send(fd_socket,sendbuf,len,0);
}
}

要将线程的建立&取消和TCP客户端循环连接服务器的代码结合起来用,才可以实现本帖的功能:

int fd_socket;
pthread_t id1;
unsigned char sendbuf[100],recvbuf[100];
void *Thread_Send_buf(void *arg)
{
int len;
while(1)
{
bzero(sendbuf,100);
scanf("%s",sendbuf);
for(len=0;sendbuf[len]!='\0';len++);
send(fd_socket,sendbuf,len,0);
}
}
int main()
{
int i=0;
int ret=-1;
socklen_t addrsize=sizeof(struct sockaddr);
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr)); // 清零
girladdr.sin_family=AF_INET;
girladdr.sin_port=htons(10086); //host-->network
girladdr.sin_addr.s_addr=inet_addr("169.254.122.1");
int thread_1=0;
while(1)
{
while(1)
{
fd_socket=socket(AF_INET,SOCK_STREAM,0);
if(fd_socket==-1)
{
printf("套接字初始化失败!\n");
return -1;
}
ret=connect(fd_socket,(struct sockaddr *)&girladdr,addrsize);
if(ret==0)
{
printf("与服务器建立连接\n");
ret=pthread_create(&id1,NULL,Thread_Send_buf,NULL);
if(ret==0)
printf("TCP发送阻塞线程被创建\n");
break;
}
}
while(1)
{
bzero(recvbuf,100);
ret=recv(fd_socket,recvbuf,100,0);
if(ret==0)
{
printf("与服务器失去连接\n");
ret=pthread_cancel(id1);
if(ret==0)
printf("TCP发送阻塞线程被取消\n");
break;
}
printf("服务器端发来信息:%s\n",recvbuf);
}
}
}

看看效果,运行程序之后,树莓派会一直检测主机的TCP服务器是否开启,如果开启了就连接,并可正常使用TCP收发:

android tcpclient框架 android tcp客户端_android tcpclient框架


至于为什么是十几秒呢,这个据以前的Linux大佬说,TCP端口重新开启需要十几秒的时间。

即使连接是断开之后再建立的,仍可正常收发:

android tcpclient框架 android tcp客户端_android tcpclient框架