当前位置: 首页 > news >正文

网络编程(三)

网络编程(三)

  • 基于UDP的网络客户端和服务端模型
    • 服务端
      • **socket**:创建网络软通道
      • **bind**:给socket套接字绑定网络终端主机信息
      • **recvfrom**:接收数据报通道中的数据
      • **sendto**:发数据
    • 客户端
  • TCP与UDP的网络通信模型区别

基于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:

#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()
{//socketint serverfd = socket(AF_INET, SOCK_DGRAM, 0);//判断socket返回值if(-1 == serverfd){perror("socket error");return -1;}//创建软通道成功printf("socket ok----\r\n");//bindstruct 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:

#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()
{//socketint clientfd = socket(AF_INET, SOCK_DGRAM, 0);//判断socket返回值if(-1 == clientfd){//返回值为-1,代表创建软通道出错,打印出错原因并返回perror("socket error \r\n");return -1;}//sendtostruct 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");}//recvfrommemset(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

相关文章:

  • JVM类加载过程
  • linux进程加载和启动过程分析
  • 解决git status提示error bad signature 0x00000000
  • 步进电机和伺服电机哪个好_步进电机和伺服电机的区别
  • 一文了解知识中台:是什么、作用、如何搭建
  • 探索UWB模块的多功能应用——UWB技术赋能智慧生活
  • C语言习题~day27
  • LINUX系统编程:信号量
  • 最新扣子(Coze)使用指南更新:如何导入扣子插件,完全免费Coze教程
  • JavaScript函数进阶学习
  • 0基础认识C语言(理论知识)
  • 算法课程笔记——计数原理
  • 直流电机工作原理与控制电路解析
  • 汇编原理(三)编程
  • Android bw_costly_<iface>链
  • [译]前端离线指南(上)
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 08.Android之View事件问题
  • canvas 绘制双线技巧
  • es的写入过程
  • mysql外键的使用
  • spring security oauth2 password授权模式
  • 安装python包到指定虚拟环境
  • 订阅Forge Viewer所有的事件
  • 构造函数(constructor)与原型链(prototype)关系
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 数据可视化之 Sankey 桑基图的实现
  • 网络应用优化——时延与带宽
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 学习笔记:对象,原型和继承(1)
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • #define、const、typedef的差别
  • #在 README.md 中生成项目目录结构
  • $.ajax,axios,fetch三种ajax请求的区别
  • (003)SlickEdit Unity的补全
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (JS基础)String 类型
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (windows2012共享文件夹和防火墙设置
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (三)docker:Dockerfile构建容器运行jar包
  • (十三)Maven插件解析运行机制
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转) 深度模型优化性能 调参
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .net 验证控件和javaScript的冲突问题
  • .NET关于 跳过SSL中遇到的问题
  • .net生成的类,跨工程调用显示注释
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?