在前面的文章中,我们使用了UDP进行网络编程,这篇文章我们就来使用另一个TCP进行网络编程,我们知道UDP和TCP都是传输层协议,但是特点不同,前者无连接,不可靠传输,面向数据报,后者有连接,可靠传输 大体框架 1.1 补充 首先,在之前的UDP网络编程中,我们是直接使用的硬编码,例如退出码直接就设为1、2、3等,显然这并不是一个很好的选择,那么这里我们可以统一设计一个服务器的退出码,就像之前设计日志等级一样 (网卡)发来的连接我们都愿意接受,所以我们地址结构中的成员 sin_addr 需要设置为 INADDR_ANY,也就是IP地址此时为0,这在UDP网络编程时我们已经详细介绍了原因,这意味着我们服务端在使用 直接向目标服务器发起建立连接的请求 return 0; } 我们这里也不需要显式bind,关于原因我们在udp网络编程时已经说明了,那我们应该做什么呢? ,上层服务我们可以和UDP网络编程一样,直接在服务端主程序调用其他的服务,就比如之前实现的翻译和路由转发,然后在服务端接收数据时,将数据回调处理,最后将结果写回客户端。
Linux Socket编程 ---- 目录 前言 Socket的功能 Socket基础 Socket类型 基本结构 基本转换函数 基本Socket使用 TCP Socket实例 UDP Socket实例 疑难问题记录 总结 ---- 前言 socket(套接字)是网络编程编程的一种技巧。 本篇不涉及太底层的网络原理,仅说明socket的基本使用方法。主要参考《Linux网络编程》。本篇源码获取方式见文底小字。 基本Socket使用 Linux同时支持面向连接和不连接类型的套接字。在面向连接的通讯中服务器和客户机在交换数据之前先要建立一个连接;在不连接通讯中数据被作为信息的一部分被交换。 网络编程非常有趣,能够实现天南海北之间的通讯,让远距离的人与人、人与物或者物与物之间产生联系,很有意思! 最后 用心感悟,认真记录,写好每一篇文章,分享每一框干货。
我们的网络编程主要就是针对应用层. 物理层我们考虑的比较少, 我们只考虑软件相关的内容. 因此很多时候我们直接称为 TCP/IP 四层模型. 再识协议 为什么要有 TCP/IP 协议? 之前我们在学习系统编程的时候知道访问公共资源就是临界资源,那么这里的局域网就是一个临界资源(以太网中, 任何时刻, 只允许一台机器向网络中发送数据)。 : IP 网络层存在的意义: 提供网络虚拟层, 让世界的所有网络都是 IP 网络, 屏蔽 最底层网络的差异 Socket 编程预备 理解源 IP 地址和目的 IP 地址 IP在网络中是用来标识主机的唯一性 sockadder结构 socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、 IPv6,以及 后面要讲的 UNIX Domain Socket. 关于Socket套接字编程后续文章会详细讲解。
文章目录 前言 一、UDP是什么 二、UDP 数据报服务特点 二、UDP 编程流程 1.服务器 2.客户端 3.输出结果 总结 前言 浅谈UDP。 二、UDP 编程流程 1.服务器 代码如下(示例): int main() { int sockfd = socket(AF_INET,SOCK_DGRAM,0); assert( sockfd
在数据进行传输之前,会先自顶向下贯穿网络协议栈完成数据的封装,其中在网络层封装的IP报头当中就涵盖了源IP地址和目的IP地址。 这时通过源IP地址+源端口号就能够在网络上唯一标识发送数据的进程,通过目的IP地址+目的端口号就能够在网络上唯一标识接收数据的进程,此时就实现了跨网络的进程间通信。 一台机器上可能会有大量的进程,但并不是所有的进程都要进行网络通信,可能有很大一部分的进程是不需要进行网络通信的本地进程,此时PID虽然也可以标识这些网络进程的唯一性,但在该场景下就不太合适了。 为什么网络字节序采用的是大端?而不是小端? 网络字节序采用的是大端,而主机字节序一般采用的是小端,那为什么网络字节序不采用小端呢? socket编程接口 socket常见接口: 创建套接字:(TCP/UDP,客户端+服务器) int socket(int domain, int type, int protocol); 绑定端口号
TCP/IP协议 TCP/IP 协议栈是一系列网络协议(protocol)的总和,是构成网络通信的核心骨架,它定义了电子设备如何连入因特网,以及数据如何在它们之间进行传输。 OSI 7层模型和TCP/IP四层网络模型对应关系 计算机网路基础的知识不过多讲解,主要是让大家明白接下来的Linux网络编程数据流属于那一层,具体如下图 TCP/IP协议数据流示意图 我们接下来讲解的 Linux网络编程Tcp协议是属于传输层的协议 Linux Socket 网络编程 TCP协议 TCP是面向连接的可靠的传输层协议。 TCP编程 Linux中的网络编程是通过socket接口来进行的。socket是一种特殊的I/O接口,它也是一种文件描述符。常用于不同机器上的进程之间的通信,当然也可以实现本地机器上的进程之间通信。 *address//协议族地址 ,socklen_t address_len); //协议族长度 - address: 协议族地址,通用的socket地址 通用的socket地址不是很好用,所以Linux
先要学习网络知识才谈得上编程 讲述计算机网络的最经典的当属Andrew S.Tanenbaum的《计算机网络》第五版,这本书难易适中。 详解的作者还写了另外2本经典著作,《Unix环境高级编程》,《Unix网络编程》二卷本。 说明:搞Linux网络编程的,想学TCP/IP的一定要看大师W.Richard Stevens这六本书,基本上六本书看完基础也就搭好了。 ? ? ? ? ? ? 他的著作有《UNIX网络编程》(两卷本),《UNIX环境高级编程》,《TCP/IP详解》(三卷本)等,同时他还是广受欢迎的教师和顾问。 网络体系结构:linux内核中网络协议的设计与实现》 ?
上篇文章我们实现了英译汉的网络字典,客服端向服务端发送英文,服务端接收数据后回调处理,将翻译后的中文再转发给客户端,这其实和EchoSever一样都是一对一的网络通信。 我们也可以实现多个客户端之间进行网络通信,通过服务端将一个客户端发送的消息转发给所有客户端,这样大家都能够看到你发的消息,以此来达到一个简易聊天室的效果。 port = std::stoi(argv[1]); Enable_Console_Log_Strategy(); // 路由服务 Route route; // 网络服务器对象提供网络通信功能 // 路由服务 Route route; // 线程池 auto tp = ThreadPool<task_t>::GetInstance(); // 网络服务器对象提供网络通信功能 这个函数由调用者提供一个缓冲区保存结果,可以规避线程安全问题; 6.2 inet_ntop - 二进制到字符串转换 功能 将网络字节序的二进制 IP 地址转换为点分十进制字符串格式。
那么这篇文章呢,我们就把客户端发来的信息当作英文单词,服务端翻译成中文再转发回去,以此来实现一个英译汉的网络字典。 1. 网络通信部分 首先我们网络通信不需要改变,只需要稍微修改添加一些新的变量,服务端在接收客户端发来的数据,然后回调去处理翻译这个动作,所以我们可以使用包装器function来包装一个函数指针,用于回调处理翻译 Udpserver.cc 服务端主程序已经有网络通信的功能了,我们现在只需要实例化字典对象,先加载字典到哈希表中,再在网络通信时进行翻译 代码如下: #include <memory> #include Enable_Console_Log_Strategy(); // 字典对象提供翻译功能 Dict dict; dict.LoadDict(); // 网络服务器对象提供网络通信功能 << "]" << word << "->" << iter->second; return iter->second; } 那么在主程序调用翻译时就需要增加参数 // 网络服务器对象提供网络通信功能
一,基础概念 数据报文在网络中的点对点传输方式通常有以下三种: 单播(Unicast): 数据报文从一个发送端到一个接收端的通信方式。 designs-examples-using-multicasting-af-inet https://os.mbed.com/handbook/Socket https://subingwen.cn/linux
在上篇文章中,我们已经铺垫了一些前置知识,这一篇文章我们就来实现UDP网络编程,实现一个Echo Server,就是客户端给服务端发送一条消息,服务端接收后,再转发给客户端,回显出来 1. :操作系统内核实现了复杂的TCP/IP协议栈,用户不能直接操作这些协议栈,所以我们说它是一组API,是应用程序与网络协议栈之间的编程接口。 这么说也没有毛病 在哲学上:我们认为它是一种抽象和解耦,它隐藏了网络协议的所有复杂性,让程序员可以用“打开-读-写-关闭”这种类似文件操作的简单模式来进行网络编程。 那还说啥了,更没毛病了 用一句话来概括,Socket(套接字)是网络通信的端点,是操作系统提供给应用程序的一组编程接口(API),应用程序通过调用这套接口,就可以利用网络协议栈(如TCP/IP)进行网络通信 /udpserver port ltx@qsy:~/gitLinux/Linux_network/SocketUDP/EchoServer$ .
网段划分 IP地址分为两部分:网络号和主机号 网络号: 保证相互连接的两个网段具有不同的标识; 主机号: 同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号; 不同的子网其实就是把网络号相同的主机放到一起 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致, 但 是主机号必须不能和子网中的其他主机重复。 通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的 IP 地址都 不相同。 那么问题来了, 手动管理子网内的 IP,是一个相当麻烦的事情。 *:前 8 位是网络号,共16,777,216 个地址 172.16.*到 172.31.*:前 12 位是网络号,共 1,048,576 个地址 192.168. ,没有 G 标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发;
在Linux系统中,我们可以通过ifconfig命令来查看自己机器的MAC地址: ether后面就是mac地址。 IP 网络层存在的意义:提供网络虚拟层,让世界的所有网络都是 IP 网络,屏蔽最底层网络的差异 最初通信依赖MAC地址,但MAC只能在局域网生效,且无法分层管理。 IP层的引入屏蔽了底层网络差异(如以太网、Wi-Fi、光纤),通过逻辑化的IP地址实现全球路由,让不同技术的网络能无缝互联。 二、socket编程预备 IP在网络中,用来标识一个主机的唯一性。 我们之前在学习系统编程的时候, 学习了 pid 表示唯一一个进程 ; 此处我们的端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系 ? 2.4、sockaddr 结构 socket API 是一层抽象的网络编程接口 , 适用于各种底层网络协议 , 如 IPv4 、 IPv6, 以及后面要讲的 UNIX Domain Socket.
,它们确保了数据在复杂的网络环境中能够准确、高效地传输,在数据发送前,发送设备会在 IP 数据包的头部封装好源 IP 地址和目的 IP 地址,然后数据在网络中传输时,路由器等网络设备会根据这些地址信息进行路由选择和数据转发 其实,端口号与进程pid,前者用来表示网络内容,后者用来表示系统内容,将网络和系统的内容进行解耦合,在一方出现问题的时候不影响另一方 2、源端口号和目的端口号 源端口号:是在网络通信中,发送数据的应用程序或进程所使用的端口号 /将一个 32 位的无符号整数从网络字节序转换为主机字节序 uint16_t ntohs(uint16_t netshort);//将一个 16 位的无符号整数从网络字节序转换为主机字节序 五、网络通信的本质 ,就是两个进程在进行进程间通信,当我们以这个视角看待网络通信的时候,那么网络通信的过程也就成了一种介质,类似于管道或者共享内存一样的通信信道 六、全面认识网络通信 在 TCP/IP 四层模型中,每一层都包含了多种不同的协议 而不仅仅是下载邮件到本地 域名系统(DNS):用于将域名解析为对应的 IP 地址,当用户在浏览器中输入域名时,DNS 服务器会将域名转换为对应的 IP 地址,以便浏览器能够找到对应的 Web 服务器 七、socket编程基础
好在Linux内核检测到TCP紧急标志时,将通知应用程序有带外数据需要接收。内核通知应用程序带外数据到达的两种常见方式是: 1O复用产生的异常事件和SIGURG信号。 对这种情况,Linux给开发人员提供的解决方案是:对监听socket设置这些socket选项,那么accept返回的连接socket将自动继承这些选项。 网络信息API 利用域名获取IP地址 IP地址比域名发生变更的概率要高,所以利用IP地址编写程序并非上策。 addrinfo结构体中,ai_ protocol 成员是指具体的网络协议,其含义和socket系统调用的第三个参数相同,它通常被设置为0。ai_fags 成员可以取表中的标志的按位或。 getnameinfo和getaddrinfo函数成功时返回0,失败时返回错误码,可能的错误码如表: Linux下strerror函数能将数值错误码error转换成易读的字符串形式,同样下面的函数可将表错误码转换成字符串形式
相关API笔记(二) Linux网络编程高级I/O函数 1. pipe pipe函数用于创建一个管道,实现进程间通信 #include <unistd.h> //成功返回0,失败返回-1并设置errno file_descriptor_two); 参数: dup和dup2的参数都是文件描述符,具体作用如下: dup函数创建一个新的文件描述符,该新的描述符和原有文件描述符file_descriptor指向相同文件,管道或者网络连接
个人主页:island1314 个人专栏:Linux—登神长阶 1. Socket 编程 6.1 socket 常见API Socket API 是一层网络编程接口,抽象了底层的网络协议,定义在 netinet/in.h 中。 实际上在网络上通信的时候套接字种类是比较多的,下面是常见的三种: unix 域间套接字编程--同一个机器内 原始套接字编程--网络工具 网络套接字编程--用户间的网络通信 设计者想将网络接口统一抽象化 --参数的类型必须是统一的,底层是一种多态的设计 运用场景: 网络套接字:运用于网络跨主机之间通信+本地通信 unix域间套接字: 本地通信 我们现在在使用网络编程通信时是应用层调传输层的接口,而原始套接字 这种设计类似于面向对象编程中的“多态”:sockaddr 可以看作一个“父类”,而 sockaddr_in 和 sockaddr_un 是它的“子类”。
网络编程基本概念 1.1 什么是套接字 套接字,也叫socket,是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户。 两个进程通信时,首先要确定各自所在的网络节点的网络地址。 一类是用户自己定义的,通常是大于1024并且小于65535的整型值; 1.3 ip地址的表示 通常我们在表达IP地址时习惯使用点分十进制表示的数值(或者是为冒号分开的十六进制Ipv6地址),而在socket编程中使用的则是二进制值 Ipv6地址),而在socket编程中使用的则是32位的网络字节序的二进制值,这就需要对这两个数值进行转换。 在linux中,最常用的是gethostbyname()和gethostbyaddr(),它们都可以实现IPv4/IPv6的地址和主机名之间的转化。
相关API笔记(一) Linux网络编程基础API 1. 通用socket地址 这个比较少用 socket网络编程接口中表示socket地址的是结构体sockaddr #include <bits/socket.h> struct sockaddr{ } 实际使用时(包括sockaddr_storage)都需要将其转化为通用的socket地址类型sockaddr(强制转换即可),所以的socket编程接口使用的类型都是sockaddr。 成功返回1,失败返回0 inet_ntoa: 网络字节序整数表示的IPv4地址转换为点分十进制表示的IPv4。 它仅能用于SOCK_DGRAM和SOCK_RAW类型的socket Y N MSG_DONTROUTE 不查看路由表,直接将数据发送给本地局域网络内的主机。
今天我们终于进入了网络编程的学习。 实际上,网络也属于操作系统的一环,我们想要学好操作系统,自然也需要去学习网络编程。 今天我们将会介绍一下网络的基础概念。 网络编程的学习与系统部分不一样,这一部分会多许多概念,我们学习的方式也更注重与概念而不是代码。 所以希望大家调整一下学习的思路。 一、计算机网络连接模式的演进 1. 应用层 : 负责应用程序间沟通,如简单电子邮件传输( SMTP )、文件传输协议(FTP )、网络远程访问协议( Telnet )等 . 我们的网络编程主要就是针对应用层 . 下面,仔细看看下面的图: 在网络传输中,我们的OS可以不同。但是我们的协议,也就是网络协议栈一定是相同的,约定好了!! 协议报头(Protocol Header)是网络数据传输时附加在数据前面的控制信息,就像快递单贴在包裹上一样。它告诉网络设备如何处理这些数据,确保数据能准确送达目的地。