0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux开发_采用线程处理网络请求

DS小龙哥-嵌入式技术 2022-09-17 15:21 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

【摘要】 介绍Linux下网络编程、线程编程,select机制,利用子线程响应TCP服务器的请求。

​TCP服务器创建流程:

1.​创建套接字

2.​绑定IP地址和端口号(创建服务器)

3.​设置监听的数量(限制最大可以连接的客户端数量)

4.​等待客户端连接

5.​实现基本通信

​TCP客户端创建流程

1.​创建套接字

2.​连接服务器

3.​实现基本通信

任务1:网络编程

练习:

1.​实现TCP服务器与TCP客户端之间的基本通信,收发数据 (按照上课的思路流程看函数文档)

2.​实现TCP服务器与TCP客户端之间的文件传输。(单个文件传输)

验证方式:(1) 同一台电脑演示 (2)同桌之间演示

考虑的问题:

(1)​网络的传输环境,考虑应答问题

(2)​数据丢包之后如何处理? 可以重发

(3)​超时处理

(4)​服务器与客户端之间连接断开处理。(客户端和服务器两边都需要重新连接)

文件传输可以在广告机中使用。

(扩展要求): 显示接收进度百分比,显示接收的文件名称,推荐: 定义结构体(使用数据结构)

3.​(扩展)实现TCP服务器与TCP客户端之间的目录传输。

4.​(扩展)实现网络聊天室(模仿QQ发送消息的效果)

​一般情况下,推荐最大每次传输的字节数不超过1024字节。

任务2:线程编程

#include

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

Compile and link with -pthread.

-lpthread

理解: 一个线程就是一个while(1)。

[root@wbyq linux-share-dir]# gcc app.c

/tmp/cccOs4TK.o: In function `main':

app.c:(.text+0x69): undefined reference to `pthread_create'

app.c:(.text+0x8d): undefined reference to `pthread_create'

collect2: ld 返回 1

[root@wbyq linux-share-dir]# gcc app.c -lpthread

练习:

1.​学习线程的基本使用

#include 
#include 
void *start_1(void *arg)
{
	while(1)
	{
		printf("123\n");
		sleep(1);
	}
}

void *start_2(void *arg)
{
	while(1)
	{
		printf("456\n");
		sleep(1);
	}
}

int main(int argc,char *argv[])
{
	pthread_t thread_1;
	pthread_t thread_2;
	pthread_create(&thread_1,NULL,start_1,NULL);
	pthread_create(&thread_2,NULL,start_2,NULL);
	while(1)
	{
		printf("789\n");
		sleep(1);
	}
	return 0;
}

2.​实现一个服务器实现多个客户端的连接,实现通信。

思路: 一个客户端就是一个独立的线程。

3.​扩展练习: 实现服务器同时对多个客户端进行文件发送。

(1)​服务器连接上一个客户端就创建一个线程。

(2)​线程的函数需要写几个? 1个

1个函数需要考虑的问题: 函数的可重入性能!

需要考虑到资源抢占! 使用信号量!

(抢答器)

设置线程分离属性:

#include 
#include 
char str1[]="123456";
char str2[]="abcdef";
void *start_1(void *arg)
{
	 printf("arg1=%s\n",arg);
	 sleep(1);
}

void *start_2(void *arg)
{
	printf("arg2=%s\n",arg);
	sleep(2);
}
int main(int argc,char *argv[])
{
	pthread_t thread_1;
	pthread_t thread_2;
	pthread_create(&thread_1,NULL,start_1,"线程1的参数传递测试");
	pthread_create(&thread_2,NULL,start_2,"线程2的参数传递测试");
	
	pthread_detach(thread_1); //设置线程的分离属性
	pthread_detach(thread_2); //设置线程的分离属性
	
	while(1)
	{
		
	}
	return 0;
}

任务3: select阻塞轮询机制

(1)​服务器什么时候收到数据? read

(2)​客户端什么时候收到数据? Read

(3)​客户端如何判断已经与服务器断开连接?

使用select机制 ,当select函数返回值为1,read函数为0就表示断开

(4)​服务器如何检测客户端已经断开连接?

采用心跳包的模式: 规定客户端每5秒钟发送一个特定的数据给服务器。

​IO 多路复用是指内核一旦发现进程指定的一个或者多个 IO 条件准备读取,它就通知该进程。

IO 条件:

(1)​网络编程中的读写

(2)​标准输出输入中的读写

#include 

#include 

#include 

#include 
select:同时可以监控多个文件描述符。
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

参数:

int nfds :最大的文件描述符+1

fd_set *readfds :读事件发生

fd_set *writefds :写事件发生

fd_set *exceptfds:出现问题

struct timeval *timeout:轮询的时间。

填NULL表示无限阻塞。

结构体里的成员填0,表示不阻塞

结构体里的成员填>0,正常的阻塞时间

返回值: 0表示没有任何事件发生,负数表示失败。>0表示发生对应的事件。
void FD_CLR(int fd, fd_set *set); //清除指定文件描述符

int FD_ISSET(int fd, fd_set *set); //检测指定的文件描述符是否发生了事件

void FD_SET(int fd, fd_set *set); //添加指定的文件描述符到fd描述符集合(多次调用)

void FD_ZERO(fd_set *set); //清除整个文件描述符集合
struct timeval {

long tv_sec; /* seconds */

long tv_usec; /* microseconds */

};

TCP服务器端处理:

#include 
#include           /* See NOTES */
#include 
#include    //使用大小端转换函数
#include 
#include 
#include 
#include 
#include 
#include 
//函数声明
void *start_routine_1(void *dev);
void *start_routine_2(void *dev);

typedef void *(*start_routine) (void *);
start_routine fun[]={start_routine_1,start_routine_2};
pthread_t thread_id[2];                //存放线程的标识符
int clientfd[2];                       //保存TCP客户端的网络套接字
struct sockaddr_in client_address[2];  //存放客户端的信息
socklen_t address_len[2];              //存放客户端结构体信息的长度
/*服务器端口号定义*/
#define P_host 8080

/*TCP服务器代码*/
int main(int argc,char *argv[])
{
	 int socketfd;
	 struct sockaddr_in server_address;     //存放服务器的IP地址信息
	 
   memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化内存空间
   memset(client_address,0,sizeof(struct sockaddr_in)*2); //初始化内存空间
   
	 server_address.sin_family=PF_INET;            //IPV4协议
	 server_address.sin_port=htons(P_host);        //端口号赋值
	 server_address.sin_addr.s_addr=INADDR_ANY;    //本地IP地址
  /*1 .创建套接字*/
   socketfd=socket(PF_INET,SOCK_STREAM,0);
   if(socketfd<0)
   	{
   	    printf("服务器网络套接字创建失败!\n");	
   	    return -1;
   	}
      	 
   /*2. 绑定端口,创建服务器*/
   if(bind(socketfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
   	{
   	    printf("服务器绑定端口失败!\n");	
   	    return -1; 	
   	}
   
   /*3. 设监听的端口数量*/
   if(listen(socketfd,10)!=0)
   	{
   		 printf("服务器端口监听失败!\n");	
   	   return -1;	 
   	}
   
    int i;
    
    for(i=0;i<2;i++)
   	{
   		 address_len[i]=sizeof(struct sockaddr);  //计算结构体大小 20 
   	  /*4. 等待客户端连接*/
	    if((clientfd[i]=accept(socketfd,(struct sockaddr *)&client_address[i],&address_len[i]))<0)
	   	{
	   	   	printf("等待客户端连接失败!\n");	
	   	    break;	
	   	} 
	    
	    //创建线程
	   	if(pthread_create(&thread_id[i],NULL,fun[i],NULL)!=0)
			{
			   printf("线程_%d_创建失败!\n",i);		
			} 	
   	}
   	
   	while(1)
   	{
   	    	
   	}
     	
   //阻塞方式等待线程的结束
	pthread_join(thread_id[0],NULL);
	pthread_join(thread_id[1],NULL);
	return 0;	
}
//线程1
void *start_routine_1(void *dev)
{
	 while(1)
	 {
	 	  printf("TCP客户端1连接!\n");
	 	  sleep(2);
	 }
	 //终止线程
	 pthread_exit(NULL);
}
//线程2
void *start_routine_2(void *dev)
{
	while(1)
	{
	 	  printf("TCP客户端2连接!\n");
	 	  sleep(2);
	}
	 //终止线程
	 pthread_exit(NULL);
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    217948
  • 编程
    +关注

    关注

    90

    文章

    3707

    浏览量

    96758
  • 线程
    +关注

    关注

    0

    文章

    508

    浏览量

    20757
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux线程对比单线程的优势

    Linux系统中,线程是操作系统能够进行运算调度的最小单位。线程被包含在进程之中,是进程中的实际运行单位。一个进程可以拥有多个线程,这些线程
    发表于 12-01 06:11

    RK3588核心板/开发板RT-Linux系统实时性及硬件中断延迟测试

    本文介绍瑞芯微RK3588芯片平台RT-Linux系统实时性及硬件中断延迟测试,基于触觉智能RK3588核心板/开发板演示。Linux-RT实时性测试测试环境说明本次测试是使用Cyclictest
    的头像 发表于 11-28 18:57 126次阅读
    RK3588核心板/<b class='flag-5'>开发</b>板RT-<b class='flag-5'>Linux</b>系统实时性及硬件中断延迟测试

    【免费送书】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    Linux系统的设备驱动开发,一直给人门槛较高的印象,主要因内核机制抽象、需深度理解硬件原理、开发调试难度大所致。2021年,一本讲解驱动开发的专著问世即获市场青睐,畅销近万册——这便
    的头像 发表于 11-18 08:06 419次阅读
    【免费送书】成为硬核<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>者:《<b class='flag-5'>Linux</b> 设备驱动<b class='flag-5'>开发</b>(第 2 版)》

    创龙 瑞芯微 RK3588 国产2.4GHz八核 工业开发板—Linux-RT应用开发案例

    Linux-RT 性能;还提供 rt_gpio_ctrl(实时线程控制 LED 翻转)、rt_input(实时线程监听按键触发 LED)两个开发案例,含测试、编译步骤与关键代码,为评
    的头像 发表于 09-25 17:25 540次阅读
    创龙 瑞芯微 RK3588 国产2.4GHz八核 工业<b class='flag-5'>开发</b>板—<b class='flag-5'>Linux</b>-RT应用<b class='flag-5'>开发</b>案例

    NVMe高速传输之摆脱XDMA设计29: TLP 请求处理流程

    请求类型为 MEM 读写请求时使用地址路由的方式。 如果请求地址在此设备 BAR 空间内, 则对 BAR 空间进行读写操作,读操作将生成 CplD, 从对应请求端口的输出端口发出;
    的头像 发表于 09-23 09:05 387次阅读
    NVMe高速传输之摆脱XDMA设计29: TLP <b class='flag-5'>请求</b><b class='flag-5'>处理</b>流程

    网络接收线程erxmb异常的原因?怎么解决?

    两个不同的软件接收组播数据久了后均出现网络数据无法接收,网络发送是正常的。lpc54628芯片。邮箱有8个但erxmb线程已经无法运行了,这是什么原因导致
    发表于 09-15 08:06

    【HZ-T536开发板免费体验】—— linux创建线程

    任务,并行是多个处理器或多核处理器同时执行不同的任务。 Linux系统中进行多线程编程时,会涉及到主线程和子
    发表于 09-01 21:31

    Linux 应用开发手册

    T507linux应用开发手册
    发表于 08-22 17:01 10次下载

    NVMe高速传输之摆脱XDMA设计之12:PCIe请求模块设计(上)

    TLP发送。由于请求时序不冲突,采用单条内部总线处理多模块请求。所有请求数据长度固定为32位双字。更多性能信息可参考B站用户名:专注与守望
    的头像 发表于 08-04 09:52 519次阅读
    NVMe高速传输之摆脱XDMA设计之12:PCIe<b class='flag-5'>请求</b>模块设计(上)

    5分钟学会网络服务搭建!飞凌i.MX9352开发板 + Linux 6.1实战示例

    本文就将以飞凌嵌入式OK-MX9352-C开发板(搭载了在工业物联网领域广泛应用的NXP i.MX9352处理器)为平台,介绍如何在Linux6.1.36开发环境当中如何搭建常用的
    的头像 发表于 06-13 16:42 1076次阅读
    5分钟学会<b class='flag-5'>网络</b>服务搭建!飞凌i.MX9352<b class='flag-5'>开发</b>板 + <b class='flag-5'>Linux</b> 6.1实战示例

    摩尔线程Linux驱动v3.0.0发布

    近日,摩尔线程正式推出Linux驱动程序v3.0.0,全面支持图形显卡MTT S80和高性能专业显卡MTT X300。作为v2.7.0RC4之后的重大升级版本,本次更新实现了多项关键技术突破:在架构
    的头像 发表于 05-08 11:38 1104次阅读
    摩尔<b class='flag-5'>线程</b><b class='flag-5'>Linux</b>驱动v3.0.0发布

    Linux主要的性能有哪些?

      什么是Linux?   Linux是一套自由传播的类Unix操作系统,是一个基于posix和unix的多用户、多任务、支持多线程和多cpu的操作系统。它的基本思想有两点,一切都是文件和每个软件
    的头像 发表于 04-30 18:09 484次阅读
    <b class='flag-5'>Linux</b>主要的性能有哪些?

    Linux网络设置与基础服务

    Linux网络设置与基础服务
    的头像 发表于 04-09 11:51 3137次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>网络</b>设置与基础服务

    服务器如何处理 HTTP 请求

    服务器处理HTTP请求的过程是一个有序且复杂的流程,通常涉及多个步骤。以下是服务器处理HTTP请求的具体步骤: 监听端口 :HTTP服务器在特定的端口(通常是80端口,除非另有指定)上
    的头像 发表于 12-30 09:37 1007次阅读

    如何调试 HTTP 请求和响应

    调试HTTP请求和响应是Web开发网络编程中的一个重要技能。以下是一些步骤和工具,可以帮助你调试HTTP请求和响应: 1. 使用浏览器开发
    的头像 发表于 12-30 09:28 1801次阅读