网络笔记(二)-套接字

网络编程套接字

IP地址:提供了一个数据传输的大致方向,并且在数据传输过程中不会被改变

IP协议分为IPV4与IPV6,一般有情况下默认为IPV4

  • IP地址是在IP协议中用来表示网络中不同主机的地址
  • 对于IPV4来说,IP地址为4字节,32比特位,对于IPV6来说,IP地址为128字节
  • IP地址一般使用“点分十进制”的字符串表示,例如 190.168.1.1
    • 用点分割的每一数字表示一个字节,范围为0-255 65535 4290000000
  • IP地址用来标识接入公网中的唯一一台主机
关于源IP地址与目的地址IP地址
  • 在IP数据包头部,有两个IP地址,源IP地址与目的IP地址,用“唐僧西天取经”的栗子理解,源IP地址就可以认为成东土大唐。而目的IP地址就可以理解为西天,在整个路程中这两个IP地址是永恒不变的,而在西天路途中所经过的小地方点就是mac地址,而mac地址是一直会改变的。

端口号(port):标识特定主机上唯一网络服务,传输层协议内容

  • 端口号是一个2字节16位的整数
  • 端口号用来表示某一台主机上的进程
  • IP地址+端口号就可以标识互联网中唯一一个进程,所以将IP地址端口号叫做Socket,也就是套接字,套接字编程,套接字通信本质上就说进程间通信,只不过是跨网络进行通信的

理解“端口号”和“进程ID”

  • 就比如10086就可以理解为“端口号”,而当你拨打10086后为你提供服务的人的工号就为“进程ID”
  • 进程一定有pid,但是不一定有端口号,当有端口号时表示为主机上要访问网络的进程

TCP/IP中最具有代表的传输层协议,TCP与UDP

关于TCP协议 (Transmission Contro Protocol 传输控制协议)
  • 保证可靠性

  • TCP面向字节流的,

    • 流就是指不间断的数据结构,当应用程序采用TCP发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。
  • 面向连接的
关于UDP协议(User Datagram Protocol 用户数据协议)
  • 无连接
  • 不可靠传输
  • UDP面向数据报
TCP与UDP
  • TCP用于传输层有必要实现可靠传输的情况下 —— 面向字节流

  • UDP主要用与一些对高速传输和实时性有较高要求的通信或广播通讯 ——面向数据报

网络字节序

  • 网络字节序默认为大端的,在发送数据时将主机序列转成网络序列,在接收数据时将网络序列转成主机序列
  • 不需要去确定主机的序列,而是将网络的序列确定好,默认为大端,当一台主机需要发送数据时,只需要将其转化成大端,而当另外一台主机收数据时,只需要将数据清一色在转化为本主机所能识别的字节序即可。

内存中的多字节数据相对于内存地址有大小端之分,磁盘文件的多字节数据相对于文件中的偏移地址也有大小端之分,而网络数据流同样有大小端之分,关于网络数据地址定义如下

  • 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出

  • 接收主机把从网络上接到的字节一次保存在接受缓冲区,也是按照地址从低到高的顺序保存

  • 因此,网络数据流的地址应该这样规定:先发出的数据是低地址,后发出的地址是高低址
  • TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节
  • 不论这台主机是大端机和小段机,都会按照TCP/IP规定的网络字节序发送/接收数据

主机序列可以和网络序列相互转换

1548566866833

  • h表示host,n表示network,l表示32位长整数,s表示16位短整数
  • htonl就是将32位的长整数从主机字节序转化为网络字节序,ntohs则相反
  • 若主机是小端字节序,这些函数将参数做相应的大小端转化
  • 若主机是大端字节序,这些函数不做转化,将参数原封不动返回

查看ip地址命令:ifconfig

TIM图片20190126171350

  • 要找到该主机所在的局域网就是通过IP地址与子网掩码按位与操作

socket编程接口


socket常见API

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建 socket ⽂件描述符 (TCP/UDP, 客户端 + 服务器) 返回文件套接字
int socket(int domain, int type, int protocol);
// 绑定端⼝号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,
socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
// 建⽴连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);

sockaddr结构

  • sockaddr结构通用数据结构:可以接受很多数据类型,可以容纳不同套接字,就类似于void
    • sockaddr 通用数据类型,相当于void (sockaddr出现在void之前)

流程:创建套接字,绑定,收发数据,关闭套接字

文件描述符,使用完需要关闭

read() 返回为0,表示对端关闭了连接

netstat -nltp 查看TCP连接

TCP在正式通讯之前要先建立连接,在建立连接时而采用三次握手

维护连接是有成本的

两次握手可能会造成大量的闲置连接而造成资源浪费

listen的第二个参数:连接队列长度,不能过长(新连接不用等待过长时间),不能没有(如果服务器端连接满载,新连接可以通过等待来建立连接 ),这样才能要保持服务器端一直处于满载工作状态。