网络编程(三)

网络编程(三)

基于UDP的网络客户端和服务端模型

服务端

  1. socket
  2. bind
  3. IO函数(recvfrom/sendto)

socket:创建网络软通道

#include <sys/types.h>

#include <sys/socket.h>
int socket(int domain, int type, int protocol);

//参数1:协议域(AF_INET)ipv4

//参数2:套接字类型-->SOCK_DGRAM 数据报套接字

//参数3:其他协议-->0:自动匹配其他需要的协议

//返回值:成功返回文件描述符,标识socket网络软通道;失败返回-1,更新errno

bind:给socket套接字绑定网络终端主机信息

#include <sys/types.h>

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

//参数1:文件描述符-->socket返回值

//参数2:指向网络终端主机信息的结构体(协议域,IP地址,端口号)

//参数3:struct sockaddr的大小

//返回值:成功返回0,失败返回-1,更新errno

//原结构体

struct sockaddr {

sa_family_t sa_family;

char sa_data[14];

};

//替换的结构体

struct sockaddr_in{

sa_family_t sin_family;

in_port_t sin_port;

struct in_adrr sin_addr;

};

struct in_addr{

__bs32 s_addr;

}

该结构体总共占16字节,两个结构体可以强转的前提是所占空间大小相同,借用struct sockaddr_in结构体存储,之后强转为struct sockaddr

recvfrom:接收数据报通道中的数据

#include <sys/types.h>

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

//参数1:文件描述符-->socket返回值

//参数2:存放接收数据的BUF

//参数3:接收数据大小

//参数4:阻塞&非阻塞的标志

//参数5:用来存放对方主机的相关信息(客户端地址)

//参数6:struct sockaddr 大小的指针

//返回值:成功返回接收到字节个数;失败返回-1,并更新errno

sendto:发数据

#include <sys/types.h>

#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

//参数1:文件描述符-->socket返回值

//参数2:存放发送数据的BUF

//参数3:接收数据大小

//参数4:阻塞&非阻塞的标志

//参数5:用来存放对方主机的相关信息(客户端地址)

//参数6:struct sockaddr 大小

//返回值:成功返回发送的字节个数;失败返回-1,并更新errno

server:

c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 20

//udpserver
int main()
{
	//socket
	int serverfd = socket(AF_INET, SOCK_DGRAM, 0);
    //判断socket返回值
	if(-1 == serverfd)
	{
		perror("socket error");
		return -1;
	}
    //创建软通道成功
	printf("socket ok----\r\n");
	//bind
	struct sockaddr_in stserver;
	stserver.sin_family = AF_INET;
	stserver.sin_port = htons(6666);
	stserver.sin_addr.s_addr = inet_addr("127.0.0.1");
	int ret = bind(serverfd, (struct sockaddr*)&stserver, sizeof(struct sockaddr));
    //判断的返回值
	if(-1 == ret)
	{
        //失败打印失败原因并返回
		perror("bind error");
		return -1;
	}
    //绑定服务端主机成功
	printf("bind ok-----\r\n");
    //接受客户端的信息
	struct sockaddr_in stclient;
    //结构体大小
	socklen_t len = sizeof(struct sockaddr);
    //创建收发数据的缓冲区
	char buf[BUF_SIZE] = {0};
	while(1)
	{
        //清空接收数据的缓冲区
		memset(buf, 0, BUF_SIZE);
        //接收客户端的信息
		ret = recvfrom(serverfd, buf, BUF_SIZE, 0, (struct sockaddr*)&stclient, &len);
        //判断返回值
		if(ret <= 0)
		{
            //接收数据失败或者没有数据,不退出,直接进行下一次客户端连接
			perror("recvfrom error or recvfrom end");
			continue;
		}
        //打印输出接收到实际的数据
		printf("recvfrom data:%s\r\n", buf);
        //清空缓冲区,为发送数据做准备
		memset(buf, 0, BUF_SIZE);
		printf("please write:\r\n");
        //从标准输入输入数据
		fgets(buf, BUF_SIZE, stdin);
        //发送数据
		ret = sendto(serverfd, buf, BUF_SIZE, 0, (struct sockaddr*)&stclient, len);
		//返回值判断
        if(ret <= 0)
		{
            //发送完毕或者发送失败,不退出,进行下一次客户端连接
			perror("sendto error or sendto end");
			continue;
		}
	}
	return 0;
}

客户端

  1. socket
  2. IO函数(sendto/recvfrom)

client:

c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//udpclient
#define BUF_SIZE 20
int main()
{
	//socket
	int clientfd = socket(AF_INET, SOCK_DGRAM, 0);
    //判断socket返回值
	if(-1 == clientfd)
	{
        //返回值为-1,代表创建软通道出错,打印出错原因并返回
		perror("socket error \r\n");
		return -1;
	}
	//sendto
	struct sockaddr_in serveraddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(6666);
	serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	socklen_t len = sizeof(struct sockaddr);
    //接收数据的缓冲区
	char buf[BUF_SIZE] = {0};
	printf("please write:\r\n");
    //从标准输入接收数据
	fgets(buf, BUF_SIZE, stdin);
    //发送数据
	int ret = sendto(clientfd, buf, BUF_SIZE,0,(struct sockaddr *)&serveraddr, len);
	if(-1 == ret)
	{
        //失败发送
		perror("sendto error");
	}
	//recvfrom
	memset(buf, 0, BUF_SIZE);
    //接收客户端的信息
	ret = recvfrom(clientfd, buf, BUF_SIZE,0,(struct sockaddr *)&serveraddr, &len);
	//返回值判断
	if(-1 == ret)
	{
        //接收失败,返回并关闭数据报套接字
		perror("recvfrom error");
        close(clientfd);
		return -1;
	}
    //否则,打印接收的数据,并关闭数据报套接字
	printf("recvfrom:%s\r\n", buf);
	close(clientfd);
	return 0;
}

TCP与UDP的网络通信模型区别

常见套接字类型

  1. 流式套接字(SOCK_STREAM) 提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设 置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。

  2. 数据报套接字(SOCK_DGRAM) 提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复, 顺序发送,可能乱序接收。

  3. 原始套接字(SOCK_RAW)--ping.c 可以对较低层次协议如IP、ICMP

  4. 直接访问 unix域套接字--》本地通信

tcp:面向连接的可靠的传输协议,通过三次握手保证可靠传送。

udp:面向无连接的不可靠的传输协议,没有三次握手,可以采用数据重传。

TCP(传输控制协议)

  1. TCP是一个可靠的,全双工的,有序的,面向链接的字节流通信的协议。
  2. 为什么可靠:
    1. 丢失的数据包重发 (能保证拿到数据)
    2. 错误的数据包重发 (保证能拿到正确的数据)
    3. 数据的有序到达(因为对每个数据包进行了编号)(拆包,编号)
    4. 有较为健全的校验机制(为了保证数据的正确性)
    5. 支持面向连接(保证通信线路的畅通)-->三次握手
    6. 有信道拥堵控制(通过一种对于信道拥堵解决的方案,来提高转发效率)产生的原因,是中继设备中(接 收的速度 >> 发送的速度)
    7. 为什么有序(有序列号):
      1. 保证数据都能传输给对端,不至于当传输的数据 > 信道带宽 ,导致数据丢弃。
      2. 通过序号,在对端主机上可以拼接成原本的数据包
      3. 保证数据传输的可靠性
      4. 如何面向链接: 三次握手和四次挥手

UDP(The User Datagram Protocol):

无连接的数据报协议,别名"不可靠的协议"

  1. 使用校验和来实现错误侦测
  2. UDP常用于媒体流的传输(音频、视频、等),在这种情况下,实时性比可靠性更重要
  3. UDP也常用于简单的查询/回应程序,例如DNS查找,在这种情况下,建立可靠传输的资源消耗太大
  4. UDP是一种实时传输协议(Real-time Transport Protocol),这种协议通常用来传输实时数据例如:音 视频流
  5. 不可靠的原因:
    1. 非面向连接(不关心接收端是否在线)--》没有三次握手
    2. 丢包不重发
    3. 错误的包不重发
    4. 没有信道拥堵控制
    5. 有一个最大传输长度限制
    6. 没有严格的校验机制
    7. 如何抉择使用TCP还是UDP
      1. 可靠性
      2. 实时性
      3. 可靠性 > 实时性: TCP 可靠性 < 实时性: UDP
相关推荐
久绊A1 小时前
网络信息系统的整个生命周期
网络
_PowerShell1 小时前
[ DOS 命令基础 3 ] DOS 命令详解-文件操作相关命令
网络·dos命令入门到精通·dos命令基础·dos命令之文件操作命令详解·文件复制命令详解·文件对比命令详解·文件删除命令详解·文件查找命令详解
_.Switch3 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
qq_254674413 小时前
工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置
网络
JokerSZ.3 小时前
【基于LSM的ELF文件安全模块设计】参考
运维·网络·安全
小松学前端6 小时前
第六章 7.0 LinkList
java·开发语言·网络
城南vision6 小时前
计算机网络——TCP篇
网络·tcp/ip·计算机网络
Ciderw7 小时前
块存储、文件存储和对象存储详细介绍
网络·数据库·nvme·对象存储·存储·块存储·文件存储
Tony聊跨境8 小时前
独立站SEO类型及优化:来检查这些方面你有没有落下
网络·人工智能·tcp/ip·ip