donatello1996 发表于 2018-12-17 09:35

【树莓派3B+测评】多线程&TCP服务器

在Linux系统中TCP通信十分常见,TCP通信可以发生在同一局域网中或跨局域网的互联网之间的设备。Linux本身就支持基于C语言的TCP/IP协议通信,需要包含以下头文件:
#include <linux/fb.h>
#include <linux/input.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>


无论是Linux还是别的系统,要进行TCP通信都有几个步骤,在源码中以函数操作简化了,对于TCP服务器初始化,分别是socket()初始化套接字,bind()绑定,listen()监听,accept()接听:
       socklen_t addrsize=sizeof(struct sockaddr);
      struct sockaddr_in sockaddr_in_comm,sockaddr_in_settings;
      //初始化该结构体变量
      bzero(&sockaddr_in_settings,sizeof(sockaddr_in_settings));
      sockaddr_in_settings.sin_family=AF_INET;
      sockaddr_in_settings.sin_addr.s_addr=inet_addr("169.254.122.5");
      sockaddr_in_settings.sin_port=htons(8086);


      fd_socket=socket(AF_INET,SOCK_STREAM,0);
      if(fd_socket==-1)
      {
                printf("套接字初始化失败!\n");
                return -1;
      }
      ret=bind(fd_socket,(struct sockaddr *)&sockaddr_in_settings,addrsize);
      if(ret==-1)
      {
                printf("套接字绑定失败!\n");
                return -1;
      }
      ret=listen(fd_socket,5);
      if(ret==-1)
      {
                printf("服务器监听失败!\n");
                return -1;
      }
      newsock=accept(fd_socket,(struct sockaddr *)&sockaddr_in_comm,&addrsize);
      if(newsock==-1)
      {
                printf("服务器接听失败!\n");
                return -1;
      }


当listen和accept操作完成之后,就可以使用recv和send两个函数进行TCP的接收和发送操作了,像上面的代码,开启了IP为169.254.122.5,端口为8086的服务器:
        while(1)
        {


            bzero(recvbuf,100);
            recv(newsock,recvbuf,100,0);
            printf("客户端发来信息:%s\n",recvbuf);


        }
注意recv函数跟scanf一样,是阻塞的,因此Linux要同时进行TCP通信接收发送的话,需要开启多线程,在main函数中使用pthread_create函数,指定函数指针,并在程序的别的地方写一个返回值为void*的函数:
pthread_create(&id1,NULL,Thread_Send_buf,NULL);


void *Thread_Send_buf(void *arg)
{
    char sendbuf;
    while(1)
    {
      bzero(sendbuf,100);
      scanf("%s",sendbuf);
      send(newsock,sendbuf,100,0);
    }
}


执行程序后,使用SSCOM或者别的软件以客户端身份登录TCP服务器,并发送一些字符串,由于TCP通信传输的单位是八位字节数据,如果在接收端不做GB2312编码判断并解码的话是无法解析中文信息的,因此发送中文会显示乱码:

然后是客户端给服务器回应信息,注意此时的sendbuf数组没有做基于发送信息长度的判断,信息的长度恒定为100,后面会以'\0'填充:

所以我们再做一个不定长发送缓冲判断算法,非常简单:


void *Thread_Send_buf(void *arg)
{
    char sendbuf;
    int len;
    while(1)
    {
      bzero(sendbuf,100);
      scanf("%s",sendbuf);
      for(len=0;sendbuf!='\0';len++);
      send(newsock,sendbuf,len,0);
    }
}


看看效果:


页: [1]
查看完整版本: 【树莓派3B+测评】多线程&TCP服务器