在线时间234 小时
UID3301905
注册时间2017-1-8
NXP金币170
TA的每日心情 | 开心 2018-4-20 15:04 |
---|
签到天数: 8 天 连续签到: 1 天 [LV.3]偶尔看看II
金牌会员
 
- 积分
- 3263
- 最后登录
- 2023-7-24
|
本帖最后由 donatello1996 于 2018-7-18 23:29 编辑
在Linux系统中,TCP通信和多线程应用都是非常常见的,并且也是经常接合使用的,因为TCP中的等待接收操作是阻塞的,倘若不使用多线程,则程序会一直轮询等待信息发过来而不执行下去。这次我,我们用几条简单的C语言语句,实现TCP通信,让板子充当TCP服务器,电脑的上位机程序充当TCP客户端。
首先是TCP服务器的建立,通过程序代码调用Linux的API:- socklen_t addrsize=sizeof(struct sockaddr);
- struct sockaddr_in boyaddr;
- struct sockaddr_in bindaddr;
- //初始化该结构体变量
- bzero(&bindaddr,sizeof(bindaddr));
- bindaddr.sin_family=AF_INET;
- bindaddr.sin_addr.s_addr=inet_addr(argv[1]);
- bindaddr.sin_port=htons(atoi(argv[2]));
- fd_socket=socket(AF_INET,SOCK_STREAM,0);
- if(fd_socket==-1)
- {
- printf("套接字初始化失败!\n");
- return -1;
- }
- ret=bind(fd_socket,(struct sockaddr *)&bindaddr,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 *)&boyaddr,&addrsize);
- if(newsock==-1)
- {
- printf("服务器接听失败!\n");
- return -1;
- }
复制代码
其中bindaddr.sin_family=AF_INET这行是直接套用的,不需要深究,要使用TCP通信就必须这样做;bindaddr.sin_addr.s_addr=inet_addr(argv[1]);bindaddr.sin_port=htons(atoi(argv[2]))这两行语句是从程序执行目录中获取IP地址和端口号,如程序编译后生成main可执行文件,则
- ./main 169.254.122.7 6666
复制代码
就是建立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客户端连上。再来看看主函数:- while(1)
- {
- bzero(recvbuf,100);
- recv(newsock,recvbuf,100,0);
- printf("客户端发来数据:%s\n",recvbuf);
- }
复制代码
由于recv()函数是阻塞的,因此主函数会一直卡在这个地方直到有TCP客户端的信息发过来。然后就是新建TCP信息发送的线程:- pthread_t id1;
- pthread_create(&id1,NULL,Scanf_Thread,NULL);
复制代码
这段代码表示新建一个名为Scanf_Thread的线程(其实就是函数),用于TCP信息的发送,我们看看新线程是怎么写的:- void *Scanf_Thread(void *arg)
- {
- int len;
- char *s;
- while(1)
- {
- bzero(s,0);
- scanf("%d",&len);
- s=(char *)malloc(len);
- scanf("%s",s);
- send(newsock,s,len,0);
- free(s);
- }
- }
复制代码
这个线程的函数名必须加*号以表示它返回值是void*的指针函数,我这里设计这个TCP发送线程是不定长发送的,发送长度由用户自定义,先输入int型正整数表示将要发送的信息的长度,再输入字符串信息。程序编译的时候要在后面加-lpthread后缀表示启用多线程:
来看看效果:
|
|