【树莓派3B+测评】TCP客户端&阻塞线程创建&取消
本帖最后由 donatello1996 于 2018-12-19 09:30 编辑【树莓派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,recvbuf;
void *Thread_Send_buf(void *arg)
{
int len;
while(1)
{
bzero(sendbuf,100);
scanf("%s",sendbuf);
//printf("----\n");
for(len=0;sendbuf!='\0';len++);
//printf("%d\n",Raspi_DHT11_Read());
send(fd_socket,sendbuf,len,0);
}
}
要将线程的建立&取消和TCP客户端循环连接服务器的代码结合起来用,才可以实现本帖的功能:
int fd_socket;
pthread_t id1;
unsigned char sendbuf,recvbuf;
void *Thread_Send_buf(void *arg)
{
int len;
while(1)
{
bzero(sendbuf,100);
scanf("%s",sendbuf);
for(len=0;sendbuf!='\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收发:
如果主机主动断开连接,那么树莓派端一样会检测到:
如果主机再次开启TCP服务器,那么树莓派会在十几秒之后重新握手建立连接:
至于为什么是十几秒呢,这个据以前的Linux大佬说,TCP端口重新开启需要十几秒的时间。
即使连接是断开之后再建立的,仍可正常收发:
页:
[1]