网络编程05

作者介绍

张伟伟,男,西安工程大学电子信息学院,2019级硕士研究生,张宏伟人工智能课题组。
微信公众号:可随时查阅,搜索—张二牛的笔记,内容会分类上传。
研究方向:机器视觉与人工智能。
电子邮件:zhangweiweicpp@163.com

了解线程池模型的设计思想
能看懂线程池实现源码
掌握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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值