网络编程-网络基础

IO进程: 进程和进程之间的通信 - 信号 信号量 消息队列 有名管道 无名管道 共享内存 套接字

套接字: 不同主机 不同操作系统之间的 进程通信

干什么: 实现无线

局域网:同一局域网下IP网段一致

IP地址

  1. IP地址 是 网络中的 主机的标识, 本质是二进制数字。

  2. IP采用 点分十进制 表示

3) IP分类: 分为 IPV4 和 IPV6 (IPV6表示的范围更广)

4) IP长度 32位 (IPV4) 64位(IPV6)

5) 每个数据包 必须要携带 目标 IP 和 源IP地址

二级划分

IP=网络号+主机号

网络号:表示是否再同一个网段内(主要是同一网段,网络号是一样的)

主机号:本网段内主机的id(主机号在同一网段下,是唯一的)

二级划分的分类

IP二级划分所表示的范围

|----|-----------------------------|----------------------|
| A类 | 0.0.0.0 - 127.255.255.255 | 大型网络 |
| B类 | 128.0.0.0 - 191.255.255.255 | 中型网络 : 管理 和 监督互联网的组织 |
| C类 | 192.0.0.0 - 223.255.255.255 | 小型网络:家用网络 ,教室网络 |
| D类 | 224.0.0.0 - 239.255.255.255 | 用于 UDP的组播通信 |
| E | 240.0.0.0 - 255.255.255.255 | 保密单位:实验室, 军方 |

特殊的IP地址

不能分配给主机使用的地址

网络地址:标识网络的起始地址,该地址不会分配到主机。(表示方式:主机号全为0的地址,为网络地址)

例: 192.168.50. 0 主机号为 0 代表 网络地址, 不会被主机分配

广播地址:用于给局域网下的所有主机发送数据使用,不会分配到主机(表示方式:主机号全为1的地址,为广播地址)

练习:

IP为192.168.1.0,同一网段最多可以连接多少个主机?

c类,最后8位为主机号,网络地址和广播地址不会被分配,256-2=254

子网掩码

作用:辅助标记IP的网络号和主机号(更快的去区分网络和主机号)

特点:网络号全置为1,主机号全部置为0

练习:

子网掩码为 255.255.255.0, 该网段最多可以容纳多少台主机

c类,最后8位为主机号,网络地址和广播地址不会被分配,256-2=254

三级划分

作用:在二级划分的基础上,再次划分,提高IP的利用率

IP=网络号+子网号+主机号

子网号:从主机号中划分出几位,充当网络号。

练习:

  1. 已知一个子网掩码号为255.255.255.192,问,最多可以连接多少台主机?

C类 255.255.255.0 - 》三级划分 -》 192 -》 1100 0000

根据子网掩码特点: 主机号全为 0

0 - 63 -》 64 -》 去掉网络地址 和 主机地址 -》 62

  1. 有两台电脑主机,在最少浪费IP地址的情况下.将172.16.14.4与172.16.13.2划归为同一网段,子网掩码应该设置为

14: 0000 11 10 255.255.252.0

13: 0000 11 01

  1. 已知IP: 192.168.50.183, 子网掩码: 255.255.255.128, 问该IP的网段为多少?

192.168.50.183 1100 0000.1010 1000. 0011 0010. 1 011 0111

子网掩码: 1111 1111. 1111 1111. 1111 1111. 1 000 0000

193.168.50.128

  1. 通过子网掩码 255.255.255.128 该子网掩码可以划分几个子网网段?

C类 -》 1 000 0000 >> 两个子网网段

0

1

2

  1. 某公司有四个部门:行政、研发1、研发2、营销,每个部门各30台计算机接入公司局域网交换机,在192.168.1.0网

段内为每个部门划分子网,子网掩码应该怎么设置,每个子网的地址范围分别是什么?(4个部门之间不能通信)

255.255.255.192

范围:

192.168.1.0-192.168.1.63

192.168.1.128-192.168.1.192

等(自己算)

网络模型

网络模型采用分层的方式,每层实现不同的功能

网络中的数据包的传输流程

osI和TCP/IP的模型对应图

UDP和TCP

相同点:都属于传输层协议,都是全双工的通信

TCP-传输控制协议

该协议是一种高可靠性的有连接的协议

TCP容易粘包

*可靠性的评判标准:

数据无丢失, 数据无失误, 数据无失序, 数据无重复到达

TCP为什么具有高可靠性( 重点

三次握手和四次挥手机制

序列号和应答号机制

超时/错误重传机制

拥堵和流量控制机制

TCP的应用场景

对于传输质量要求较高的场合,以及大量数据传输的场合。

UDP-用户数据报协议

该协议是一种不可靠的无连接的协议

UDP是一种容易造成丢包的协议,不保证数据的完整性

UDP的应用场景

应答较为困难的网络中可以使用UDP。

socket套接字

什么是socket

  1. socket是一个编程接口
  2. socket是一个特殊的文件描述符
  3. socket是一种通信机制
  4. 一套用于建立连接的数字

socket的类型

流式套接字(SOCK_STREAM)对应协议-TCP

特点:面向连接,可靠性高的数据传输服务

数据报套接字(SOCK_DGRAM)对应协议-UDP

特点:无连接的,不可靠的数据传输服务

原始套接字(SOCK_RAM)

特点:较低层次的协议,例入ICMP中使用

socket的功能

socket可以在计算机中创建两个缓存区,一个是发送缓存区,一个是接收缓存区。

端口号

为了区分一台主机接收到的数据包,应该交给那个进程来处理

端口号的长度:2byte(IP长度为4byte)

众所周知端口(被占用): 0~1023(1~255之间为众所周知端口,通常由UNIX系统占用)

比如 文件传输端口 TFTP 端口号为 69

已登记端口:1024~49151 (---- 可用来建立与其它主机的会话**----)**

动态或私有端口:49152~65535--固定某些服务使用--

字节序

字节序:不同类型的CPU主机,内存存储大于一个字节类型的数据,在内存中的存放顺序

分类:

主机字节序(小端):地址低位存放数据低位,地址高位存放数据高位

网络字节序(大端):地址高位存放数据低位,地址地位存放数据高位

在主机上的字节序一般都为主机字节序。在网络中传输的数据,大于一个字节的数据类型,必须转换为网络字节序

端口号转换专用接口

复制代码
头文件: #include<arpa/inet.h>
原型:  u_long htonl (u_long hostlong)     u_short htons (u_short short)
//端口号一般为 1024 - 49151, 两个字节足够,基本不需要long
功能: 主机字节序的端口 转 网络字节序 
           
原型:  u_long ntohl (u_long hostlong);   u_short ntohs (u_short short);
功能: 网络字节序的端口 转 主机字节序

IP转换专用接口

复制代码
 in_addr_t  inet_addr(const char *strptr);
头文件:   #include<sys/socket.h>   #include<netinet/in.h>    #include<arpa/inet.h>
原型:       //该参数是字符串
功能:    主机字节序(点分十进制形式的IP) 转为网络字节序
参数:     const char *strptr: 字符串

       typedef uint32_t in_addr_t;  (通过vi -t 追一下)
            struct in_addr { 
                        in_addr_t   s_addr;
            }; 
返回值: 返回一个无符号长整型数(无符号32位整数用十六进制表示), 
            否则NULL

char *inet_ntoa(struct in_addr in);
头文件 :   #include <arpa/inet.h>  #include<sys/socket.h>  #include<netinet/in.h>              
功能:    将网络字节序二进制地址转换成主机字节序。 
参数:     stuct in_addr in addr  : 只需传入一个结构体变量,该变量代表IP
返回值:  返回一个字符指针, 否则NULL;

TCP编程

socket创建套接字

复制代码
函数原型:
int socket(int domain, int type, int protocol);

调用形式:
socket(协议族,套接字类型,0);

参数domain:协议族
参数type:套接字类型
参数protocol:传0,表示根据第二个参数自动匹配协议

返回值:创建成功返回sockfd描述符(0->标准输入,1->标准输出,2->标准错误,3->自定义创建的socket)
        创建失败返回-1,更新errno

bind绑定套接字

vi -t :查询数据类型的shell指令

复制代码
函数原型:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
头文件: #include<sys/types.h>  #include<sys/socket.h> 
         #include<netinet/in.h>  #include<netinet/ip.h>

功能:绑定 IP 和 port

参数:
    sockfd:套接字
    addr:用于通信结构体 (提供的是通用结构体,需要根据选择通信方式,填充对应结构体-通信当时socket第一个参数确定,需要强转)
         (结构体之间的强转,不可以直接使用普通数据类型强转,因为结构体字节对齐原则,具体大小不一致,会数据丢失,所以可使用结构体指针,对结构体地址进行强转)   
    addrlen:结构体大小   
    
返回值:成功 0   失败-1,更新errno
  
 通用结构体:
  struct sockaddr {
     sa_family_t  sa_family;
     char        sa_data[14];
 }

ipv4通信结构体:
struct sockaddr_in {
    sa_family_t    sin_family;  ----协议族
    in_port_t      sin_port;   ----端口
    struct in_addr sin_addr;     ----ip结构体
};
struct in_addr {
    uint32_t       s_addr;     --ip地址
};

listen监听

复制代码
int listen(int sockfd, int backlog);
功能:监听,将主动套接字变为被动套接字
参数:
 sockfd:套接字
 backlog:等待连接队列中,客户端请求链接的最大个数,不能写0.
        一般写6-8个

返回值:成功 0   失败-1,更新errno  

accept阻塞等待连接

复制代码
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

功能:阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,
             则accept()函数返回,返回一个用于通信的套接字文件;
参数:
   Sockfd :套接字
   addr: 链接客户端的ip和端口号
      如果不需要关心具体是哪一个客户端,那么可以填NULL;
   addrlen:结构体的大小
     如果不需要关心具体是哪一个客户端,那么可以填NULL;
返回值: 
     成功:通信的文件描述符; 
     失败:-1,更新errno新errno  

recv接收数据

复制代码
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能: 接收数据 
参数: 
    sockfd: acceptfd ;
    buf  存放位置
    len  大小
    flags  一般填0
             MSG_DONTWAIT  非阻塞
返回值: 
   < 0  失败出错  更新errno
   ==0  表示客户端退出
   >0   成功接收的字节个数

练习

  1. 服务器可以循环接收客户端的数据;

  2. 当客户端退出后, 服务器阻塞等待下一个客户端的连接,而后继续通信;

  3. 当有客户端连接时, 服务器端 打印客户端的IP 和 Port信息;

  4. 将代码的 send 和 recv 改为 write 和 read, 测试一下效果;

  5. 利用argv[ ] 采用终端输入的方式, 输入IP 和 Port ,从而bind绑定;

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <wait.h>
    #include <signal.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <semaphore.h>
    #include <sys/msg.h>
    #include <sys/shm.h>
    #include <sys/un.h>

    typedef struct sockaddr_in addr_in_t;
    typedef struct sockaddr addr_t;
    typedef struct sockaddr_un addr_un_t;
    int main(int argc, const char *argv[])
    {
    while(1)
    {
    //创建套接字
    //AF_INET---ipv4协议族
    //SOCK_STREAM---流式套接字(TCP)
    //0---根据第二个参数自动匹配协议
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0)
    {
    perror("socket is err");
    return -1;
    }

    复制代码
     	//bind绑定套接字
     	struct sockaddr_in saddr;
     	saddr.sin_family = AF_INET;
     	//将主机字节序的端口号转换为网络字节序
     	int port;
     	char p[128]={0};
     	printf("请输入Port:");
     	scanf("%d",&port);
     	printf("请输入IP:");
     	scanf("%s",p);
     	saddr.sin_port = htons(port);
     	saddr.sin_addr.s_addr = inet_addr(p);
    
    
     	//绑定填充的结构体属性到sockfd套接字上
     	int bindfd = bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
     	if(bindfd<0)
     	{
     		perror("bind is err");
     		//return -1;
     	}
     	printf("%ld %ld\n",sizeof(saddr),sizeof(struct sockaddr_in));
    
     	//listen监听 创建监听队列
     	int listenfd = listen(sockfd,5);
     	if(listenfd < 0)
     	{
     		perror("listen is err");
     		return -1;
     	}
    
     	//建立通信
     	//如果没有客服端链接,accept回阻塞等待客户端链接
     	//第二个参数用于获取来链接的客服端的信息
     	//返回值为一个进行通信的文件描述符
     	printf("accept.......\n");	
     	struct sockaddr_in aaddr;
     	int len = sizeof(aaddr);
     	aaddr.sin_family = AF_INET;
     	//int acceptfd = accept(sockfd,NULL,NULL);	
     	int acceptfd = accept(sockfd,(struct sockaddr*)&aaddr,&len);	
     	int kfport = ntohs(aaddr.sin_port);
     	char* kfip = inet_ntoa(aaddr.sin_addr);
     	printf("客服端端口:%d\n客服端IP为:%s\n",kfport,kfip);
     	if(acceptfd < 0)
     	{
     		perror("accept id err");
     	char buf[128]={0};
     		return -1;
     	}
    
     	//接收数据
     	//accept是建立通信的文件描述符(不能用sockfd)
     	//第四个参数常用0和MSG_NOWAIT
     	//0---表示阻塞,如果没有数据接收,则阻塞等待
     	//MSG_NOWAIT---表示非阻塞
     	while(1)
     	{
     		char buf[128]={0};
     		int recfd = recv(acceptfd,buf,sizeof(buf),0);
     		if(recfd < 0)
     		{
     			perror("recv is err");
     			return -1;
     		}
     		else if(recfd == 0)
     		{
     			printf("client is exit\n");
     			break;
     		}
     		else
     		{
     			printf("client输入的数据为:%s\n",buf);
     		}
     	}
    
     	close(sockfd);
     	close(acceptfd);
     }
     return 0;

    }

相关推荐
BingoGo17 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack17 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack3 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
DianSan_ERP3 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
feifeigo1233 天前
matlab画图工具
开发语言·matlab
dustcell.3 天前
haproxy七层代理
java·开发语言·前端
norlan_jame3 天前
C-PHY与D-PHY差异
c语言·开发语言