网络编程笔记

网络编程

1. 概念

1.1 局域网

局域网:局域网将一定区域的各种计算机、外部设备和数据连接起来形成计算机通信的私有网络

广域网:又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程公共网络

1.2 IP

本质是一个整形数,用于表示计算机在网络中的地址。IP协议版本有两个:IPV4和IPV6

  • IPV4

    1. 使用一个32位的整形数表示一个IP地址,4个字节,int型

    2. 也可以使用点分十进制字符串描述这个IP地址:192.168.10.27

    3. 分成四份,每份1字节,8bit(char),最大值255

      1. 0.0.0.0是最小的ip地址
      2. 255.255.255.255是最大的IP地址

​ 4. 按照IPV4协议计算,可以使用的IP地址有2的32次方个

  • IPV6

    1. 使用一个128位的整形数描述一个IP地址,16个字节

    2. 也可以使用一个字符串描述这个IP地址:2001:0db8:3c4d:0015:0000:0000:1a2b

    3. 分成了8份,每份2字节,每一部分以16进制的方式表示

    4. 按照协议IPV6计算,可以使用的IP地址有2的128次方个

      在这里插入图片描述

    在这里插入图片描述

1.3 端口

作用:定位到主机上的某一个进程,通过这个端口进程就可以接受对应的网络数据

端口也是一个整形数unsigned short,一个16位整型数,有效端口取值范围:0~65535

注意:一个进程不需要网络通信的话就不需要绑定端口,如果需要网络通信那么就需要绑定,一个端口对应一个进程,多个进程不能同时使用一个端口

1.4 OSI/ISO 模型

OSI,即开放式系统互联,一般都叫OSI参考模型。是ISO(国际标准化组织)在1985年研究的网络互联模型

在这里插入图片描述

2. 网络协议

TCP UDP IP 以太网

3. socket 编程

socket 对于程序员来说是一套网络通信接口,使用这套接口可以完成网络通信,网络通信主要分为两部分:客户端和服务器端。

需要了解三个概念:IP、端口、通信数据

3.1 字节序

概念:大于一个字节类型的数据在内存中的存放顺序,也就是说对于单字符来说是没有字节序问题,字符串是单字符的集合,因此字符串也没有字节序问题。

计算机通常采用的字节存储机制主要有两种:Big-endian大端存储和little-endian小端存储

  • 小端->主机字节序

    数据的低位字节存储到内存的低地址位,数据的高位字节存储到内存的高地址位

    PC机默认使用小端存储

  • 大端->网络字节序

    数据的低位字节存储到内存的高地址位,数据的高位字节存储到内存的低地址位

    套接字通过过程中操作的数据都是大端存储,包括:接收/发送数据、IP地址、端口

    4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit

​ 0x12 34 56 78

​ 小端:78 56 34 12

​ 大端:12 34 56 78

3.2 大小端转换函数

#include <arpa/inet.h>
/*
u:unsigned
16:16位
h:host,主机字节序
n:net,网络字节序
s:short
l:int
*/
uint16_t htons(uint16_t hostshort);
uint32_t htonl(uint32_t hostlong);

uint16_t ntohs(uint16_t netshort);
uint32_t ntohl(uint32_t netlong);

3.3 IP地址转换

  • 字符串类型的IP地址转换为大端整型数

    int inet_pton(int af , const char *src, void *dst );
    /*
    af:地址族协议
    AF_INET4:ipv4格式的ip地址
    AF_INET6:ipv6格式的ip地址
    
    src:传入参数,对应要转换的点分十进制的ip地址:192.168.10.27
    dst:传出参数,函数调用完成,转换得到的大端整形IP被写入到这块内存中
    
    返回值:成功1,失败0或-1
    */
    
  • 大端整型数转换为小端的点分十进制的IP地址

    #include <arpa/inet.h>
    
    const char *inet_ntop(int af,const void *src,char *dst,socklen_t size);
    /*
    src:传入参数,指向大端整形数的地址
    dst:传出参数,指向小端点分十进制的IP地址字符串
    size:dst的内存大小
    返回值:成功返回a non-null pointer to dst
    	   失败返回NULL  with errno set to indicate the error
    */
    
  • 只能用于IPV4大小端转换的函数(一般不用)

    //IP->大端整形
    in_addr_t inet_addr(const char *cp);
    
    // 大端整形 -> 点分十进制ip
    char *inet_ntoa(struct in_addr in);
    

4. TCP 通信流程

TCP报文长度

在这里插入图片描述

TCP是一个面向连接的,安全的,流式传输协议,这个协议是传输层协议

  • 面向连接:是一个双线连接,通过三次握手完成,断开连接需要通过四次挥手
  • 安全:tcp通信过程中,会对发送的每一数据包都会进行校验,如果发现数据丢失会自动重传
  • 流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致

在这里插入图片描述

4.1 服务器端通信流程
int lfd = socket(int domain, int type, int protocol); //创建用于监听的socket,lfd是一个文件描述符
bind();             //将得到的监听的文件描述符和本地的IP端口进行绑定
listen();           //设置监听(成功之后开始监听,监听的是客户端的连接)
int cfd = accept(); //等待并接受客户端的连接请求,建立新的连接,会得到一个新的文件描述符(通信的)
read(); /recv();//通信读写默认都是阻塞的
write();/send();
close();//断开连接,关闭套接字  **调用一次挥手两次**
4.2 客户端通信流程

在单线程的情况下客户端通信的文件描述符有一个,没有监听的文件描述符

int cfd = socket();//创建一个通信的套接字
connect(); //连接服务器,需要知道服务器绑定的IP和端口
// 接收数据
read();/recv();
//发送数据
write();/send();

close(); //断开连接,关闭文件描述符(套接字)
4.3 socket函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
/*
domain 用于指定一个通信域;这将选择将用于通信的协议族。
TCP/IP协议来说,AF_INET\AF_INET6\AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE

type 指定套接字的类型

protocol 通常设置为 0,表示为给定的通信域和套接字类型选择默认协议。
当对同一域和套接字类型支持多个协议时,可以使用 protocol 参数选择一个
特定协议。在 AF_INET 通信域中,套接字类型为SOCK_STREAM 的默认协议是
传输控制协议(Transmission Control Protocol,TCP 协议)。
在 AF_INET 通信域中,套接字类型为 SOCK_DGRAM 的默认协议时 UDP。
*/

在这里插入图片描述

*注意*:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

4.4 bind函数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定(将套接字与地址进行关联)。

struct sockaddr{
   
    sa_family_t sa_family;
    char sa_data[14];
};
/*sa_data 是一个 char 类型数组,一共 14 个字节,在这 14 个字节中就包括了 IP 地址、端口
号等信息*/
typedef uint32_t in_addr_t;
struct in_addr{
   
    in_addr_t s_addr;
};
struct sockaddr_in {
   
 	sa_family_t sin_family; /* 协议族 AF_INET*/
 	in_port_t sin_port; /* 端口号   大端*/  
 	struct in_addr sin_addr; /* IP 地址    大端*/
 	unsigned char sin_zero[8];
};
/*
sin_port,sin_addr,会组成sa_data,然后传递给bind
*/

//`````````````````````````使用示例```````````````````````````````````````````

int socket_fd = socket(AF_INET, SOCK_STREAM, 0);//打开套接字
if (0 > socket_fd) {
   
 perror("socket error");
 exit(-1);
}

struct sockaddr_in socket_addr;
memset(&socket_addr, 0x0, sizeof(socket_addr)); //清零
//填充变量
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(5555);
bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(socket_addr));

·····
    
close(socket_fd);
4.5 listen函数

                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值