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

Linux-C socket网络通信 03.25

socket网络通信 03.25


整体结构类似

依然属于进程间的通信

网络三要素:

IP地址:确定网络中某一台计算机的位置

端口号:确定是哪个应用程序

通信协议:通信时,通信双方预定好的规则

应用程序是静态的,电脑运行起来就是进程

越往上,越偏向软件;越往下,越偏向硬件

数据从应用层开始,每向下一次,会打包一次,直至物理层

TCP:

1、通信时候一定要验证通信双方是否都在线(验证的是,客户端与对应的服务器是否都在线)

2、传输介质:流式IO(byte)

3、理论上,每一次的传输不会限制大小

UDP:

1、不用验证是否在线

2、传输介质:数据报文包

3、每次只能传输64KB

TCP牺牲效率,提高传输的稳定性;UDP牺牲稳定性,提升效率

在大部分使用情况下,TCP连接外网,UDP连接本机;UDP适合在不管对方是否在线的情况下使用

本机IP—网络回环地址:127.0.0.1

ping 127.0.0.1 ping给自己,再自己接收

IPV4:8个字节,

服务器:被动连接

客户端:主动发送请求

SOCKET分类:

•流式套接字(SOCK_STREAM):流式的套接字可以提供可靠的、面向连接的通讯流。它使用了TCP协议。TCP 保证了数据传输的正确性和顺序性。

•数据报套接字(SOCK_DGRAM):数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。使用数据报协议UDP协议。

•原始套接字(SOCK_RAW):原始套接字允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实现的测试等。

sockaddr套接字地址结构:
structsockaddr{unsignedshortsa_family;//address族, AF_xxxcharsa_data[14];//14 bytes的协议地址};//sa_family 一般来说, IPV4使用“AF_INET”。//sa_data 包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一起的
sockaddr_in地址结构:
structsockaddr_in{shortintsin_family;//Internet地址族unsignedshortintsin_port;//端口号structin_addrsin_addr;//Internet地址unsignedcharsin_zero[8];//添0(和struct sockaddr一样大小)};structin_addr{union{unsignedlongints_addr;}};

注:sockaddr和sockaddr_in两个数据类型是等效的,可以相互转换,通常使用sockaddr_in更为方便

sin_port----字节顺序转换函数:

四个函数的功能:网络字节顺序与本地字节顺序之间相互转换

•htons()——“Host to Network Short” –主机字节顺序转换为网络字节顺序(对无符号短型进行操作2bytes)

• htonl()——“Host to Network Long” –主机字节顺序转换为网络字节顺序(对无符号长型进行操作4bytes)

• ntohs()——“Network to Host Short”–网络字节顺序转换为主机字节顺序(对无符号短型进行操作2bytes)

• ntohl()——“Network to Host Long ”–网络字节顺序转换为主机字节顺序(对无符号长型进行操作4bytes)

之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO。

网络字节顺序NBO(Network Byte Order):

按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题(大端:低位存放在高字节)。

主机字节顺序(HBO,Host Byte Order):

不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关(小端:低位存放在低字节)。

如 Intel x86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12 。

如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78。

由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序 。在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换。

socket()函数:

功能:为了执行I/O,服务端和客户端必须先调用socket(),产生TCP套接字,作为TCP通信的传输端点;

返回:调用成功,则返回一个较小的非负整数,失败则返回-1;

intsocket(intfamily,inttype,intprotocol);//指明协议族family=AF_INET;//IPv4协议;family=AF_INET6;//IPv6协议;family=AF_ROUTE;//路由套接口。//指明产生套接字的类型type=SOCK_STREAM;//字节流套接口,TCP常用的形式;type=SOCK_DGRAM;//数据报套接口,UDP常用的形式 ;type=SOCK_RAW;//原始套接口//protocol是协议标志,一般在调用socket()时将其设置为0。(但如果是原始套接字,就需要为其指定一个常值)
bind()函数

功能:为调用socket()函数产生的套接字(socketfd)分配一个本地协议地址,建立地址与套接字(socketfd)的对于关系。

返回:该函数调用成功返回0,若出错则返回-1,并置错误号errno;

intbind(intsockfd,conststructsockaddr*server,socklen_len addrlen);//sockfd参数是套接字函数返回的套接字描述符;//server参数是指向特定于协议的地址结构的指针,指定用于通信的本地协议地址;//addrlen参数是指定该套接字地址结构的长度;
listen()函数

功能:将未连接的套接字转换成被动套接字,使它处在监听模式下,指示内核应接受发向该套接字(socketfd)的连接请求。

返回:调用成功返回0,若出错则返回-1,并置errno值;

intlisten(intsockfd,intbacklog);//sockfd参数是要设置的描述符;//backlog参数规定了请求队列中的最大连接数;
accept()函数

功能:使服务器接受客户端的连接请求。函数由 TCP 服务器调用,用于从已完成连接队列队头返回下一个已完成连接。如果已完成连接队列为空,那么进程被进入睡眠。

返回:调用成功:

(1)accept()函数的返回值,已连接套接字描述符;
(2)addr参数参会客户端的协议地址,包括IP地址和端口号等;
(3)addrlen参数返回客户端地址结构的大小。

如果调用失败则返回-1,并置errno值。

intaccept(intsockfd,structsockaddr*addr,socklen_t*addrlen);//sockfd参数是由sockfd()函数产生的套接字描述符,在调用accept()函数前,已经调用listen()函数将此套接字变成了监听套接字;//addr参数是用来返回连接对方(客户端)的套接字地址结构;//addrlen参数是用来返回连接对方的套接字的结构长度
connect()函数

功能:让TCP客户端使用来配置套接字,建立一个与TCP服务器的连接。(激发TCP的三次握手过程)

返回:调用成功后返回0,若出错则返回-1;

intconnect(intsockfd,conststructsockaddr*addr,socklen_t addrlen);//sockfd参数是有sockd()函数返回的套接字描述符;//addr参数是指向服务器的套接字地址结构的指针;//addrlen参数是该套接字地址结构的大小
close()函数

功能:关闭套接字,并立即返回到进程。

intclose(intsockfd);

特殊文件描述符号:

•标准输入STDIN_FILENO

•标准输出STDOUT_FILENO

•标准错误STDERR_FILENO

每个进程被加载后,默认打开0,1,2这三个文件描述符

htons()

头文件:#include <arpa/inet.h>

unsignedshortinthtons(unsignedshortinthostshort);

Server

#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>using namespace std;intmain(){structsockaddr_ins_addr;intlen=0;charbuf[50]={0};intsocketfd=0;intacceptfd=0;intclient_num=0;socketfd=socket(AF_INET,SOCK_STREAM,0);if(socketfd==-1){perror("socket error");}else{s_addr.sin_family=AF_INET;//ipv4s_addr.sin_addr.s_addr=INADDR_ANY;//Internet地址s_addr.sin_port=htons(10086);len=sizeof(s_addr);if(bind(socketfd,(structsockaddr*)&s_addr,len)==-1){perror("bind error");}sleep(1);if(listen(socketfd,10)==-1)//监听,判断 请求队列中的最大连接数为10{perror("listen error");}cout<<"ready OK"<<endl;//网络通道准备好了while(1)//死循环,保证服务器长时间运行{cout<<"wait"<<endl;acceptfd=accept(socketfd,NULL,NULL);//等待客户端上线,阻塞式函数,没有响应,会一直在//返回客户端的IP地址cout<<"client line succuss --- acceptfd="<<acceptfd<<endl;//网络只能从4开始,0 1 2分别表示操作系统标准输入、输出、报错;3是文件IO操作时候文件描述符号client_num++;if(!fork())//开辟子进程进行后续工作{while(1){read(acceptfd,buf,sizeof(buf));printf("Get msg from client%d: %s\n",client_num,buf);bzero(buf,sizeof(buf));}}}}close(socketfd);return0;}

Client

#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<iostream>#include<stdio.h>#include<string.h>using namespace std;intmain(){structsockaddr_ins_addr;intlen=0;intsocketfd=0;charbuf[50]={0};//socketfd=socket(AF_INET,SOCK_STREAM,0);if(socketfd==-1){perror("socket error");}else{s_addr.sin_family=AF_INET;s_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//本机回环ip地址即虚拟机ip 192.168.136.0s_addr.sin_port=htons(10086);len=sizeof(s_addr);//客户端向服务器发送连接请求if(connect(socketfd,(structsockaddr*)&s_addr,len)==-1){perror("connect error");}else{cout<<"connect success"<<endl;while(1){cin>>buf;write(socketfd,buf,sizeof(buf));}}}close(socketfd);return0;}

桥接与NAT连接:

  • 虚拟机网络在桥接连接方式下,虚拟机的ip为主机下的网段,若主机ip地址改变,则虚拟机ip也会改变

  • 虚拟机网络在NAT连接方式下,会生成始终固定的局域网段,而虚拟机的ip为网段中的一个ip地址,因此NAT连接相比桥接,有优点是虚拟机的ip不受系统ip地址变化而变化

http://www.jsqmd.com/news/471760/

相关文章:

  • 一键解锁 N 种快乐, 蘑兔ai音乐也太会了
  • PDF.js实战:教你给企业官网嵌入可定制化的PDF阅读器(附源码)
  • JavaScript 事件循环机制与宏任务/微任务解析
  • Wireshark抓取RTP流实战:从H264封装到播放全流程解析(附常见问题排查)
  • TypeScript 类型系统与泛型编程实践
  • 钓鱼邮件反查
  • 3.2 交换机的包转发操作
  • 海康威视摄像机二次开发避坑指南:从SDK集成到萤石云接入的实战经验
  • TypeScript 装饰器与元数据反射机制:探索代码增强的新维度
  • 订单管理模块避坑指南:从物流进度条到省市联动的3个典型问题解决方案
  • YOLO11检测中的模型分块加载策略:讲解如何在内存有限的设备上动态加载模型
  • React 虚拟 DOM 与 Diffing 算法原理解析
  • UniApp实战:5分钟搞定Google登录集成(附完整代码)
  • 企业内网安全实战:H3C AC与思科AAA服务器联动配置全流程(附避坑指南)
  • 602 传奇游戏:复古、高爆、打金一网打尽
  • 深入MTK Camera数据流:从Sensor到ISP的完整路径解析与性能优化技巧
  • Kubernetes 恢复虚拟机快照后 Pod 一直 ContainerCreating,Calico Unauthorized 问题排查全过程(新手踩坑记录)
  • Android Studio SDK安装踩坑实录:从代理设置到HAXM安装的完整解决方案
  • CH9120芯片实战:5分钟搞定以太网转串口透传(附配置工具下载)
  • OpenClaw 智能搜索 Skill 创建:从零到一的保姆级图文教程
  • Python → WASM+WASI编译避坑手册:12个生产环境踩过的坑,第7个90%开发者仍在犯
  • Claude Cowork:10GB 虚拟机暗中运行,安全还是负担?
  • Charles抓包工具安卓配置:为什么你的手机请求看不到?(附最新证书解决方案)
  • LoadRunner四大版本实战指南:从Professional到Developer的选型与部署策略
  • 实战解析:如何通过requestrepo高效检测XXE漏洞
  • OpenStreetMap:开源地图如何挑战科技巨头的垄断地位
  • 小白也能看懂!3分钟掌握AI Agent设计模式,收藏这份进阶指南!
  • Gaussian如何计算垂直激发能
  • 西门子S7-1200与V90伺服PN口通信实战:从GSD安装到轴控制全流程
  • 基于ChatGPT3.5的车辆计数数据集优化:从CARPK到PUCPR+的标注转换实践