查看: 3522|回复: 2

[i.MX6ULL竞赛专区] 【我的项目666--智能楼宇门禁】TCP服务器&多线程

[复制链接]
  • TA的每日心情
    开心
    2018-4-20 15:04
  • 签到天数: 8 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    49

    主题

    188

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    3263
    最后登录
    2023-7-24
    发表于 2018-7-11 09:45:22 | 显示全部楼层 |阅读模式
    本帖最后由 donatello1996 于 2018-7-18 23:29 编辑

        在Linux系统中,TCP通信和多线程应用都是非常常见的,并且也是经常接合使用的,因为TCP中的等待接收操作是阻塞的,倘若不使用多线程,则程序会一直轮询等待信息发过来而不执行下去。这次我,我们用几条简单的C语言语句,实现TCP通信,让板子充当TCP服务器,电脑的上位机程序充当TCP客户端。
        首先是TCP服务器的建立,通过程序代码调用Linux的API:
    1.     socklen_t addrsize=sizeof(struct sockaddr);
    2.     struct sockaddr_in boyaddr;
    3.     struct sockaddr_in bindaddr;
    4.     //初始化该结构体变量
    5.     bzero(&bindaddr,sizeof(bindaddr));
    6.     bindaddr.sin_family=AF_INET;
    7.     bindaddr.sin_addr.s_addr=inet_addr(argv[1]);
    8.     bindaddr.sin_port=htons(atoi(argv[2]));

    9.     fd_socket=socket(AF_INET,SOCK_STREAM,0);
    10.     if(fd_socket==-1)
    11.     {
    12.             printf("套接字初始化失败!\n");
    13.             return -1;
    14.     }
    15.     ret=bind(fd_socket,(struct sockaddr *)&bindaddr,addrsize);
    16.     if(ret==-1)
    17.     {
    18.             printf("套接字绑定失败!\n");
    19.             return -1;
    20.     }
    21.     ret=listen(fd_socket,5);
    22.     if(ret==-1)
    23.     {
    24.             printf("服务器监听失败!\n");
    25.             return -1;
    26.     }
    27.     newsock=accept(fd_socket,(struct sockaddr *)&boyaddr,&addrsize);
    28.     if(newsock==-1)
    29.     {
    30.             printf("服务器接听失败!\n");
    31.             return -1;
    32.     }
    复制代码




    其中bindaddr.sin_family=AF_INET这行是直接套用的,不需要深究,要使用TCP通信就必须这样做;bindaddr.sin_addr.s_addr=inet_addr(argv[1]);bindaddr.sin_port=htons(atoi(argv[2]))这两行语句是从程序执行目录中获取IP地址和端口号,如程序编译后生成main可执行文件,则
    1. ./main 169.254.122.7 6666
    复制代码
    28.jpg
    就是建立IP为169.254.122.7,端口号为6666的TCP服务器。socket(AF_INET,SOCK_STREAM,0)是建立套接字;bind(fd_socket,(struct sockaddr
    *)&bindaddr,addrsize)是绑定套接字;listen(fd_socket,5)是监听TCP客户端的连接;accept(fd_socket,(struct sockaddr *)&boyaddr,&addrsize)是接受TCP的客户端的连接,程序会卡在accept()函数中直到有TCP客户端连上。再来看看主函数:
    1.     while(1)
    2.     {
    3.         bzero(recvbuf,100);
    4.         recv(newsock,recvbuf,100,0);
    5.         printf("客户端发来数据:%s\n",recvbuf);
    6.     }
    复制代码

    由于recv()函数是阻塞的,因此主函数会一直卡在这个地方直到有TCP客户端的信息发过来。然后就是新建TCP信息发送的线程:
    1.     pthread_t id1;
    2.     pthread_create(&id1,NULL,Scanf_Thread,NULL);
    复制代码

    这段代码表示新建一个名为Scanf_Thread的线程(其实就是函数),用于TCP信息的发送,我们看看新线程是怎么写的:
    1. void *Scanf_Thread(void *arg)
    2. {
    3.     int len;
    4.     char *s;
    5.     while(1)
    6.     {
    7.         bzero(s,0);
    8.         scanf("%d",&len);
    9.         s=(char *)malloc(len);
    10.         scanf("%s",s);
    11.         send(newsock,s,len,0);
    12.         free(s);
    13.     }
    14. }
    复制代码


    这个线程的函数名必须加*号以表示它返回值是void*的指针函数,我这里设计这个TCP发送线程是不定长发送的,发送长度由用户自定义,先输入int型正整数表示将要发送的信息的长度,再输入字符串信息。程序编译的时候要在后面加-lpthread后缀表示启用多线程:


    31.jpg
    来看看效果:
    29.jpg 30.jpg



    今天心情不错
    回复

    使用道具 举报

  • TA的每日心情

    2017-1-4 08:05
  • 签到天数: 11 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    85

    主题

    1629

    帖子

    1

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2569

    优秀版主

    最后登录
    2019-3-28
    发表于 2018-7-13 08:47:57 | 显示全部楼层
    -lpthread表示链接线程库
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2018-10-17 09:43
  • 签到天数: 47 天

    连续签到: 1 天

    [LV.5]常住居民I

    21

    主题

    135

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    487
    最后登录
    2022-10-24
    发表于 2018-7-13 14:01:34 | 显示全部楼层
    签到签到
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-8-11 02:42 , Processed in 0.084527 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表