UNIX-Linux网络通信
计算机网络
概念
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和消息传递的计算机系统。
计算机网络的功能
数据通信、资源共享、提高系统的可靠性、分布式网络处理和负载均衡。
计算机网络的组成
通信子网:网卡、线缆、集线器、中继器、交换机(交换跟计算机之间的数据)、路由器(网络跟网络之间的通信)。
资源子网:网络中的计算机、打印机、电话等一些可以提供服务的设备。
计算机网络软件:
协议软件:它规定了计算机之间通信的规则,TCP/IP协议簇。
网络通信软件:网络中实现计算机与设备之间通信的软件(网卡驱动)。
网络管理软件:防火墙、SELinux
网络应用软件:浏览器、迅雷
网络操作系统:可以提供给网络服务的计算机操作系统。Windows server2008、UNIX、Linux
计算机网络的分类
按网络作用范围划分:局域网、城域网、广域网
按网络技术划分:广播式网络、点对点网络
按传输介质划分:有线网、无线网、微波通信、卫星通信。
计算机网络拓扑结构
星型、树型、总线型、环型、网状型
计算机网络的发展过程
1、以计算机为中心的联系系统。
2、分组交换网络的诞生。
3、网络体系结构与协议标准化
20世纪80年代ISO组织提出开放式系统参考模型(OSI,Open System Interconnect)
但由于这个模型照顾到了各方的利益,所以太过庞大,因此至今都没有成熟的产品,目前我们所使用是一系列协议的集合,简称TCP/IP簇,通常也叫TCP/IP协议模型。
目前所有的计算机系统都按照这份协议进行通信,所以不同的操作系统之间才可以进行网络通信。
C/C++/Java/python->Windows->socket->TCP/IP<->TCP/IP->socket->Linux->C/C++/Java/python
4、高速计算机网络
网卡
它负责将数据发送到网络上,也负责从网络中获取数据,每个网卡上都有一个独一无二MAC地址。
OSI参考模型与TCP/IP参考模型
网络协议是为网络数据交换而制定的规则、约束、标准,一个功能完备的计算机网络需要制定一套完整的协议集,目前的网络协议是按层次结构组织的,网络层次结构模型与个协议的集合称为网络体系结构。
OSI从下到上一共七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP目前只实现了四层,从下到上:
物理层:负责通信网络收发数据包
网络层:选择、流量控制、网络拥塞,IP协议是该层的核心
传输层:负责机器之间建立用于会话的端到端连接(数据传输),该层的核心是TCP/UDP。
应用层:为用户提供了针对性的服务,这一层的代表协议有:HTTP浏览器,SMTP简单邮件传输协议,FTP文件传输协议,SNMP简单网络管理协议(防火墙),TELNET远程登录的标准协议。
OSI TCP
-----------------------------
物理层
数据链路层 物理层
------------------------------
网络层 网络层
------------------------------
传输层 传输层
------------------------------
会话层
表示层 应用层
应用层
IP地址
在计算机网络中每一台计算机都必须有一个唯一的标识(MAC地址不容易记忆),它就是IP地址,目前在计算机以.分十进制表示(4个不超过255的整数),但在程序中它就是4字节的整数。
IP地址的分类:A、B 公有 C私有(可重复) D类用于广播和组播多播 E类保留
A类:第一个二进制位必须是0
0.0.0.0~127.255.255.255
B类:前两位的二进制必须是10
128.0.0.0~191.255.255.255
C类:前三位二进制必须是110
192.0.0.0~223.255.255.255
D类:前四位二进制必须是1110
224.0.0.0~239.255.255.255
E类:前四位二进制必须是1111
240.0.0.0~255.255.255.255
公有IP和私有IP
公有IP:在网络服务提供商登记过的IP叫公有IP。(所有的计算机可以直接访问)
私有IP:由一些公司或组织自己分配的,不能再网络中直接公开访问的。
子网掩码
由4个不超过255的整数,以.分十进制表示。
网络地址=IP地址 按位与 子网掩码
只有在统一子网内的IP地址才可能直接进行通信,否则必须经过路由器。
网关地址
负责子网出口的计算机,一般由路由器担任(路由器就是一台具有路由功能的计算机)。
端口号
IP地址能决定我们与哪台计算机通信,而端口号决定了我们与计算机上的哪个进程通信。
1~1024基本上已经被操作系统预定完了,因此我们在编程时一般1024以上。
http:80 ftp:21 ssh:22 telnet:23
网络通信的基本概念
TCP和UDP的区别
TCP:传输控制协议,面向连接的服务,安全、可靠(三次握手、响应+重传、四次挥手),速度相对较慢,一般应用在对安全性、完整性有严格要求的场景:ftp文件传输、邮件SMTP、网页HTTP
三次握手:
A要知道,A能到B,B也能到A。
B要也要知道,A能到B,B也能到A。
四次挥手
目的是保证关闭前发送完所有数据包(应用层已经交给底层了,但底层还没有完全发送出去)。
A 发送关闭请求-> B
A <-发送请求响应 B
B检查是否有未发送完成的数据
A <-可以关闭 B
A 发送确认关闭-> B
消息流
应用层->表示层->会话层->网络层->传输层->数据链路层->物理层->物理层->数据链路层->传输层->网络层->会话层->表示层->应用层
消息包
当socket收到要发送的数据时,会先把数据进行拆分成Bit流,然后再组成(防丢失)数据包(可能会丢包)。
socket(套接字)
socket是一种接口机制,可以让程序无论使用什么端口、协议,都可以从socket进出数据,它负责了进程与协议之间的连接。
编程模式
点对点(p to p):一对一通信
客户机/服务器(C/S):一对多
创建socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
功能:创建socket描述符,可以把socket当作文件来看待,发送数据就是写文件,接收数据就是读文件。
domain:地址类型
AF_UNIX/AF_LOCAL/AF_FILE 本地通信(进程间通信)
AF_INET 基本32位IP地址通信,IPv4版本
AF_INET6 基本128位IP地址通信,IPv6版本
type:通信协议
SOCKET_STREAM 数据流协议,TCP
SOCKET_DGRAM 数据包协议,UDP
protocol:特别通信协议,给0即可
返回值:socket描述符
通信地址
注意:函数接口定义的是sockaddr,而实际提供的是sockaddr_un或sockaddr_in。
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct sock_un{
_SOCKADDR_COMMON (sun_); // 地址类型 参看domain参数
char sum_path[108]; // socket文件路径
};
struct sockaddr_in{
_SOCKADDR_COMMON (sin_);
in_port_t sin_port; // 端口号 大端字节序
struct in_addr sin_addr; // IP地址 大端4字节整数
};
struct in_addr{
in_addr_t s_addr;
};
绑定
socket描述符与物理通信载体(网卡或socket文件)绑定在一起。
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket描述符:函数返回值
addr:通信地址结构体,实际给的是sock_un或sockaddr_in,需要强制类型转换
addrlen:通信地址结构体类型的字节数,使用sizeof计算
连接
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket描述符
addr:通信目标地址
addrlen:通信地址结构体类型的字节数,使用sizeof计算
返回值:在不同的编程模型下返回值意义不同,在本地通信
成功返回0失败返回-1.
数据的接收与发送:read/write
ssize recv(int sockfd,void *buf,size_t len,int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
recv/send与read/write功能一样,flags多了是否阻塞的功能(0阻塞/1不阻塞)。
关闭套接字:close
如果是网络通信,端口号并不会立即回收,大概会占用3分钟左右。
字节序转换
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
功能:把32位本机字节序转换成32位的网络字节序
uint16_t htons(uint16_t hostshort);
功能:把32位本机字节序转换成16位的网络字节序
uint32_t ntohl(uint32_t netlong);
功能:把32位网络字节序转换成32位本机字节序
uint16_t ntohs(uint16_t netshort);
功能:把16位网络字节序转换成16位本机字节序
IP地址转换
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
功能:把点分十进制的IP地址(字符串)转换成32位无符号整数,使用指针来获取
in_addr_t inet_addr(const char *cp);
功能:把点分十进制的IP地址(字符串)转换成32位无符号整数
char *inet_ntoa(struct in_addr in);
功能:把32位无符号整数的IP地址,转换成点分十进制的IP地址(字符串)
本地通信编程模型
进程A 进程B
创建套接字AF_LOCAL 创建套接字AF_LOCAL
准备地址sockaddr_un 准备地址sockaddr_un
绑定自己的socket和地址 连接connect,连接进程A的地址
接收数据 发送数据
关闭套接字 关闭套接字
基于TCP协议的C/S/模型
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:设置等待连接的最大数量
sockfd:被监听的socket描述符
backlog:等待连接的最大数量(排队的数量)
成功返回0失败返回-1
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等待连接,sockfd连接
addr:获取连接的地址
addrlen:设置连接地址结构体的长度
返回值:专门用于通信的描述符
编程模型
Server Client
创建socket套接字 创建socket套接字
准备地址(sockaddr_in,本机地址) 准备地址(服务端地址)
绑定(bind) ...
监听(listen) ...
等待连接(accept、fork) 连接(connect)
接收请求(read/recv) 发送请求(write/send)
响应请求(write/send) 接收响应(read/recv)
关闭(close) 关闭(close)
与阿里云ESC服务器进行网络通信
1、开启端口号
2、使用Flash FXP上传代码
3、使用putty远程登录ECS服务器,修改代码、编译、执行
基于UDP协议的C/S模型
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
功能:UDP协议专用的数据发送函数
sockfd:套接字描述符
buf:待发送的缓冲区首地址
len:待发送的数据长度
flags:是否阻塞 0阻塞/1不阻塞
dest_addr:目标计算机地址
addrlen:地址结构体的字节数
返回值:成功发送的字节数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
功能:UDP协议专用的数据接收函数
sockfd:套接字描述符
buf:数据存储位置
len:最大接收字节数
flags:是否阻塞 0阻塞/1不阻塞
src_addr:获取发送者的IP地址
addrlen:设置地址结构体的字节数
返回值:成功发送的字节数
编程模型
Server Client
创建套接字socket 创建套接字socket
准备本机地址sockaddr_in 准备目标机地址sockaddr_in
绑定bind(sockfd+addr) ...
接收请求recvfrom 发送请求sendto
响应请求sendto 接收响应recvfrom
关闭套接字close 关闭套接字close
注意:从服务器到客户端返回的路线是UDP协议自己设计的。
Windows下的网络编程
一般的软件都是Linux/UNIX作为服务器,而Windows系统作为客户端,Windows下socket编程的接口与Linux基本一致,函数都声明在winsock2.h头文件中。
int WSAStartup(WORD,LPWSADATA);
功能:初始化网络库
WORD:设置网络库的版本
MAKEWORD(1,2),第一位主版本号,第二位副版本号
LPWSADATA:WSADATA数据结构的指针,用来获取网络库的相关信息
closesocket(sockfd);
功能:关闭socket
int WSACleanup(void);
功能:卸载网络库
注意:编译时添加 -lws2_32
注意:在Windows下write/read(只用于文件读写)
send/recv用于网络通信