作者介绍
张伟伟,男,西安工程大学电子信息学院,2019级硕士研究生,张宏伟人工智能课题组。
微信公众号:可随时查阅,搜索—张二牛的笔记,内容会分类上传。
研究方向:机器视觉与人工智能。
电子邮件:zhangweiweicpp@163.com
- 课题组CSDN官方账号,欢迎一键三连: https://blog.csdn.net/m0_37758063/article/details/113527955?spm=1001.2014.3001.5501.
了解线程池模型的设计思想
能看懂线程池实现源码
掌握tcp和udp的优缺点和使用场景
说出udp服务器通信流程
说出udp客户端通信流程
独立实现udp服务器代码
独立实现udp客户端代码
熟练掌握本地套接字进行本地进程通信
1.线程池(day05-视频4-10需要复习)
应用需要频繁的创建和销毁线程,若干个线程组合到一起, 形成线程池;实现的时候类似于生产者和消费者。
线程池和任务池,主线程和子线程相关关系:
任务池相当于共享资源, 所以需要使用互斥锁, 当任务池中没有任务的时候需要让线程阻塞, 所以需要使用条件变量.
2.简单版本的线程池流程分析
- 一些细节:
-
shutdown:是销毁子线程的变量标识。
-
job_pop:取任务的位置变量
- 待补充。。。。。。。
3.UDP通信(TCP和UDP的区别重要面试题)
- TCP:
传输控制协议, 面向连接的,稳定的,可靠的,安全的数据流传递,数据拆分
稳定和可靠: 丢包重传
数据有序: 序号和确认序号
流量控制: 滑动窗口 - UDP:
用户数据报协议
面向无连接的,不稳定,不可靠,不安全的数据报传递-–更像是收发短信
UDP传输不需要建立连接,传输效率更高,在稳定的局域网内环境相对可靠。
4.UDP相关函数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
函数说明: 接收消息
参数说明:
sockfd 套接字
buf 要接受的缓冲区
len 缓冲区的长度
flags 标志位 一般填0
src_addr 原地址 传出参数
addrlen 发送方地址长度
返回值
成功: 返回读到的字节数
失败: 返回 -1 设置errno
调用该函数相当于TCP通信的recv+accept函数
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
函数说明: 发送数据
参数说明:
sockfd 套接字
dest_addr 目的地址
addrlen 目的地址长度
返回值
成功: 返回写入的字节数
失败: 返回-1,设置errno
5.UDP的通信流程
5.1 UDP通信服务端和客户端流程
man 7 UDP
UDP的服务器编码流程:
创建套接字 type=SOCK_DGRAM
绑定ip和端口
while(1)
{
收发消--recvfrom
发消息--sendto
}
关闭套接字--close
UDP客户端流程:
创建套接字--socket
while(1)
{
收发消--recvfrom
发消息--sendto
}
关闭套接字--close
5.2 UDP服务端代码编写
//udp服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
int main()
{
//创建socket
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd<0)
{
perror("socket error");
return -1;
}
//绑定
struct sockaddr_in serv;
struct sockaddr_in client;
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(cfd, (struct sockaddr *)&serv, sizeof(serv));
int i;
int n;
socklen_t len;
char buf[1024];
while(1)
{
//读取数据
memset(buf, 0x00, sizeof(buf));
len = sizeof(client);
n = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr *)&client, &len);
//将大写转换为小写
for(i=0; i<n; i++)
{
buf[i] = toupper(buf[i]);
}
printf("[%d]:n==[%d], buf==[%s]\n", ntohs(client.sin_port), n, buf);
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&client, len);
}
//关闭套接字
close(cfd);
return 0;
}
5.3 UDP客户端代码编写
测试使用 :
nc -u 127.1 8888
//udp客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
int main()
{
//创建socket
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd<0)
{
perror("socket error");
return -1;
}
int n;
char buf[1024];
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
while(1)
{
//读标准输入数据
memset(buf, 0x00, sizeof(buf));
n = read(STDIN_FILENO, buf, sizeof(buf));
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&serv, sizeof(serv));
//读取数据
memset(buf, 0x00, sizeof(buf));
n = recvfrom(cfd, buf, sizeof(buf), 0, NULL, NULL);
printf("n==[%d], buf==[%s]\n", n, buf);
}
//关闭套接字
close(cfd);
return 0;
}