Linux 系统应用编程——网络编程(socket编程)

二、网络编程基础

1、套接字概述

       套接字就是网络编程的ID。网络通信,归根到底还是进程间的通信(不同计算机上的进程间的通信)。在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址,两个进程通信时,首先要确定各自所在网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中哪一个进程通信,因此套接口中还需要有其他的信息,也就是端口号(port)。在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一一对应的关系。所以,使用端口号和网络地址的组合就能唯一确定整个网络中的一个网络进程。

      把网络地址和端口号信息放在一个结构体中,也就是套接口地址结构,大多数的套接口函数都需要一个指向套接口地址结构的指针作为参数,并以此来传递地址信息。每个协议族都定义了它自己的套接口地址结构,套接字地址结构都以"sockaddr_” 开头,并以每个协议族名中两个字母作为结尾。

     下面是socket所在位置:

可以看到套接口有3种类型:

1)流式套接字(SOCK_STREAM)

      流式套接字提供可靠的、面向连接的通信刘,保证数据传输的可靠性和按序收发。TCP通信使用的就是流式套接字。

2)数据包套接字(SOCK_DGRAM)

      数据报套接字实现了一种不可靠、无连接的服务。数据通过相互独立的报文进行传输,是无序的,并且不保证可靠的传输。UDP通信使用的就是数据报套接字。

3)原始套接字(SOCK_RAW)

     原始套接字允许对底层协议(如IP或ICMP)进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。

 

2、端口号

      这里的端口号是逻辑意义上的端口,一般是指TCP/IP 协议中的端口,端口号的范围为0~65535,比如用于浏览网页服务(HTTP协议)的80端口,用于FTP服务的21端口等。其中, 0 到1023 一般被系统程序所使用。

     那么TCP/IP协议中的端口指的是什么呢?举个例子,如果IP地址唯一指定了地球上某个地理位置的一间房子,端口号就是出入这间房子的门,只不过这个房子的门有65536个之多,端口是通过端口号来标记的,端口号是一个16位的整数,范围是从0~65535。

    端口号只具有本地意义,即端口号只是为了标识本地计算机上的各个进程。在互联网中不同计算机的相同端口号是没有联系的。16bit 的端口号可允许有64K个端口号,这个数目对一个计算机来说是足够用的。

 

3、IP地址

1)IP地址的作用

       IP地址用来表示网络中的一台主机。准确的说,IP地址是一台主机到一个网络的一个连接,因为现在一个主机中会有多个网卡。

      一个IP地址包含两部分:网络号和主机号。其中,网络号和主机号根据子网掩码来区分。简单的说,有了源IP 和目标 IP,数据包就能在不同主机之间传输。

2)IP地址格式转换

      IP地址有两种不同格式:十进制点分形式和32位二进制形式。前者是用户熟悉的形式,而后者则是网络传输中IP地址的存储方式。

      这里主要介绍IPV4地址转换函数,主要有 inet_addr() 、inet_aton() 、inet_ntoa() 。前两者的功能都是将字符串转换成32位网络字节序二进制值,第三个将32位网络字节序二进制地址转换成点分十进制的字符串。

inet_addr() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_addr(const char *strptr);
参数

strptr :要转换的IP地址字符串

函数返回值

成功:32位二进制IP地址(网络字节序)

出错:-1

inet_aton() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_aton(int family, const char *src , void *drt);
参数

family   AF_INET:IPV4协议

             AF_INET6:IPV6协议

src:要转换的IP地址字符串

函数返回值

成功:32位二进制IP地址(网络字节序)

出错:-1

inet_ntoa() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_ntoa(int family, const char *src , void *dst, size_t len);
参数

family   AF_INET:IPV4协议

             AF_INET6:IPV6协议

src:要转换的二进制IP地址;
dst:存放十进制地址字符串的缓冲区;
len:缓冲区的长度

函数返回值

成功:返回dst

出错:NULL

 

4、字节序

      字节序又称为主机字节序 Host Byte Order,HBO,是指计算机中多字节整型数据的存储方式。字节序有两种:大端(高位字节存储在低位地址,低位字节存储在高位地址)和小端(和大端序相反,PC通常采用小端模式)。

      为什么需要字节序?在网络通信中,发送方和接收方有可能使用不同的字节序;


为了保证数据接受后能被正确的解析处理,统一规定:数据以高位字节优先顺序在网络上传输。因此数据在发送前和接收后都需要在主机字节序和网络字节序之间转换。



1)函数说明

      字节序转换涉及4个函数:htons() 、ntohs() 、htonl() 和 ntohl() 。这里的 h 代表 host , n 代表 network , s 代表 short , l 代表 long 。通常 16bit 的IP端口号用前两个函数处理,而 IP 地址用后两个函数来转换。调用这些函数只是使其得到相应的字节序,用户不需要知道该系统的主机字节序和网络字节序是否真的相等。如果两个相同不需要转换的话,该系统的这些函数会定义成空宏。

2)函数格式

所需头文件#include <netinet/in.h>
函数原型unit16_t htons(unit 16_t hostshort);
unit32_t htonl(unit 32_t hostlong);
unit16_t ntohs(unit 16_t netshort);
unit32_t ntohl(unit 32_t netlong);
函数传入值hostshort:主机字节序的16bit 数据
hostlong :主机字节序的32t 数据
netshort  :网络字节序的16bit 数据
netlong:网络字节序的32bitt 数据
函数返回值成功:返回转换字节序后的数值
出错:-1

5、TCP编程

函数说明

socket()编程的基本函数有socket() 、bind()、listen()、accept()、send()、sendto()、recv()以及recvfrom()等。下面先简单介绍上述函数的功能,再结合流程图具体说明

1)socket() :该函数用于创建一个套接字,同时指定协议和类型。

2)bind()     :该函数将保存在相应地址结构中的地址信息与套接字进行绑定。它主要用于服务器端,客户端创建的套接字可以不绑定地址。

3)listen()   :在服务端程序成功建立套接字并与地址进行绑定以后,通过调用listen() 函数将TCP连接后,该函数会返回一个新的已连接套接字。

5)connect():客户端通过该函数向服务器端的监听套接字发送连接请求。

6)send() 和 recv():这两个函数通常在TCP通信过程中用于发送和接收数据,也可用于UDP中。

7)sendto()和recvfrom() :这两个函数一般在UDP通信过程中用于发送和接受数据。当用于TCP时,后面的几个与地址有关的参数不起作用,函数作用等同于 send() 和 recv()


服务器端和客户端使用TCP的流程如下:



可以看到通信工作的大致流程如下:

1)服务器先用socket() 函数来建立一个套接口,用这个套接口完成通信的监听及数据的收发;

2)服务器用bind() 函数来绑定一个端口号和IP地址,使套接口与制定的端口号和IP地址相关联;

3)服务器调用listen()函数,使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。

4)客户机调用socket()函数建立一个套接口,设定远程IP和端口。

5)客户机调用 connect() 函数链接远程计算机指定的端口。

6)服务器调用 accept() 函数来接受远程计算机的连接请求,建立起与客户机之间的通信连接。

7)建立连接以后,客户机用write() 函数 (或send()函数)向socket() 中写入数据,也可以用 read() 函数(或recv()函数)读取服务器发送来的数据。

8)服务器用 read()函数(或recv()函数)读取客户机发送来的数据,也可以用 write() 函数(或send()函数)来发送数据。

9)完成通信以后,使用close()函数关闭socket 连接。


函数格式:

1)创建套接口 socket() 函数

其语法要点

所需头文件#include <sys/socket.h>
函数原型 int socket(int family, int type,int protocol);
函数传入值family:协议族
type:套接字类型
protocol:0(原始套接字除外)
函数返回值成功:非负套接字描述符
出错:-1

参数family 指明协议族,取值如:

AF_INET:IPv4协议

AF_INET6:IPv6协议

AF_LOCAL:UNIX域协议

AF_ROUTE:路由套接字

AF_KEY:密钥套接字

这里“AF”代表“Adress Family”(地址族)

types指明通信字节流类型,其取值如:

SOCK_STREAM:流式套接字(TCP方式)

SOCK_DGRAM:数据包套接字(UDP方式)

SOCK_RAM:原始套接字


2)绑定端口 bind()函数

     用socket() 函数创建一个套接口后,需要使用bind 函数在这个套接口上绑定一个指定的端口号和IP地址。bind函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
函数传入值sockfd:套接字描述符
my_addr:绑定的地址
addrlen:地址长度
函数返回值成功:0
出错:-1

这里my_addr是IPv4地址,IPv4 套接口地址数据结构以socketaddr_in 命名,定义在 <netinet/in.h>头文件中,形式如下:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct sockaddr_in   
  2.   
  3. sa_family_t    sin_family; /* address family: AF_INET */  
  4. in_port_t      sin_port;   /* port in network byte order */  
  5. struct in_addr sin_addr;   /* internet address */  
  6. ;  

sin_famliy 为套接字结构协议族,如IPv4为AF_INET;

sin_port  是16位 TCP或UDP端口号,网络字节顺序;

结构体成员in_addr也是一个结构体,定义如下:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct in_addr  
  2. {  
  3.     uint32_t s_addr;     /* address in network byte order */  
  4. };  
这里s_addr为32位IPv地址,网络字节顺序; 本地地址可以用INADDR_ANY;

字节排序函数上面已经介绍,下面看一个实例:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <sys/types.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8. #include <unistd.h>  
  9. #define PORT 2345  
  10.   
  11. int main()  
  12. {  
  13.     int sockfd;  
  14.     struct sockaddr_in addr;  
  15.     int addr_len = sizeof(struct sockaddr_in);  
  16.   
  17.     if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)  
  18.     {  
  19.         perror("socket fail");  
  20.         exit(-1);  
  21.     }  
  22.     else  
  23.     {  
  24.         printf("socket created successfully!\nsocket id is %d\n",sockfd);  
  25.     }  
  26.   
  27.     memset(&addr,0,addr_len);  
  28.     addr.sin_family = AF_INET;  
  29.     addr.sin_port = htons(PORT);  
  30.     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  31.   
  32.     if(bind(sockfd,(struct sockaddr *)(&addr),addr_len) < 0)  
  33.     {  
  34.         perror("bind error");  
  35.         exit(-1);  
  36.     }  
  37.     else  
  38.     {  
  39.         printf("bind port successfully!\nlocal port:%d\n",PORT);  
  40.     }  
  41.   
  42.     return 0;  
  43. }  
执行结果如下:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. fs@ubuntu:~/qiang/net$ ./socket   
  2. socket created successfully!  
  3. socket id is 3  
  4. bind port successfully!  
  5. local port:2345  
  6. fs@ubuntu:~/qiang/net$   


3)等待监听函数

      所谓监听,指的是socket 的端口一直处于等待的状态,监听网络中的所有客户机,耐心等待某一客户机发送请求。如果客户端有连接请求,端口就会接受这个连接。listen 函数用于实现服务器的监听等待功能,它的函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int listen(int sockfd, int backlog);
函数传入值sockfd:套接字描述符
backlog:请求队列中允许的最大请求数,大多数系统默认值为5
函数返回值成功:0
出错:-1

需要注意的是listen 并未真正的接受连接,只是设置socket 的状态为监听模式,真正接受客户端连接的是accept 函数 。通常情况下,listen 函数会在 socket ,bind 函数之后调用,然后才会调用 accept 函数。

     listen函数只适用于SOCK_STREAM或SOCK_SEQPACKET 的socket 类型。如果socket 为 AF_INET ,则参数 backlog 最大值可设至128,即最多可以同时接受128个客户端的请求。

 

4)接受连接函数

      服务器处于监听状态时,如果模式可获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时,再处理客户机的连接请求,接受连接请求的函数时accept,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数传入值

sockfd:套接字描述符

my_addr:用于保存客户端的地址,入参

addrlen:地址长度

函数返回值

成功:建立好连接的套接字描述符

出错:-1

 当 accept 函数接受一个连接时,会返回一个新的 socket 标识符,以后的数据传输与读取就是通过这个新的socket 编号来处理,原来参数中的 socket 也可以继续使用。接受连接以后,远程主机的地址和端口信息会保存在 addr 所指的结构体内。

下面是个实例,体验listen 、accept函数的使用:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <sys/socket.h>  
  6. #include <unistd.h>  
  7. #include <netinet/in.h>  
  8. #include <arpa/inet.h>  
  9. #define PORT 2345  
  10.   
  11. int main()  
  12. {  
  13.     int sockfd,newsockfd;  
  14.     struct sockaddr_in addr,caddr;  
  15.     int addr_len = sizeof(struct sockaddr_in);  
  16.     int caddr_len = sizeof(struct sockaddr_in);  
  17.   
  18.     if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)  
  19.     {  
  20.         perror("socket error");  
  21.         exit(-1);  
  22.     }  
  23.     else  
  24.     {  
  25.         printf("socket successfully!\n");  
  26.         printf("socket id : %d\n",sockfd);  
  27.     }  
  28.   
  29.     memset(&addr,0,addr_len);  
  30.     addr.sin_family = AF_INET;  
  31.     addr.sin_port = htons(PORT);  
  32.     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  33.   
  34.     if(bind(sockfd,(struct sockaddr *)&addr,addr_len) == -1)  
  35.     {  
  36.         perror("bind error");  
  37.         exit(-1);  
  38.     }  
  39.     else  
  40.     {  
  41.         printf("bind successfully!\n");  
  42.         printf("local port : %d\n",PORT);  
  43.     }  
  44.   
  45.     if(listen(sockfd,5) == -1)  
  46.     {  
  47.         perror("listen error");  
  48.         exit(-1);  
  49.     }  
  50.     else  
  51.     {  
  52.         printf("listening...\n");  
  53.     }  
  54.   
  55.     if((newsockfd = accept(sockfd,(struct sockaddr *)&caddr,&caddr_len)) == -1)  
  56.     {  
  57.         perror("accept error");  
  58.         exit(-1);  
  59.     }  
  60.     else  
  61.     {  
  62.         printf("accepted a new connection ..\n");  
  63.         printf("new socket id : %d\n",newsockfd);  
  64.     }  
  65.   
  66.     return 0;  
  67. }  

执行程序,得到输出结果:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. fs@ubuntu:~/qiang/netprogram/tmp$ ./lisacc   
  2. socket successfully!  
  3. socket id : 3  
  4. bind successfully!  
  5. local port : 2345  
  6. listening...  

程序运行到这停止,并一直在这里等待,说明本机计算机的 2345号端口正处于监听的状态,等待本机上的连接服务请求。此时打开浏览器,在浏览器地址栏中输入下列形式的地址:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. http://192.168.3.51:2345/  

这个地址是笔者个人IP地址,按"ENTER" 键,这样浏览器会请求连接本地计算机上的2345号端口。此时终端中显示如下结果:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. accepted a new connection ..  
  2. new socket id : 4  

表明程序已经接受了这个连接,并创建了一个新的套接口(ID为4),然后退出了程序。

 

5、请求连接函数

       所谓请求连接,是指在客户机向服务器发送信息之前,需要先发送一个连接请求,请求与服务器建立TCP通信连接。connect 函数可以完成这项功能,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int connect(int sockfd, struct sockaddr * serv_addr, int addrlen);
函数传入值

sockfd:套接字描述符

sock_addr:服务器端地址

addrlen:地址长度

函数返回值

成功:0

出错:-1

这里ser_addr 是一个结构体指针,指向一个sockaddr 结构体,这个结构体存储着远处服务器的IP与端口号信息。


6、数据读写函数

TCP/UDP读写函数总结,注意函数要成对使用

1)send函数

     建立套接口并完成通信连接以后,可以把信息传送到远程主机上,这个过程就是信息的发送。而对于远程主机发送来的信息,本地主机需要进行接收处理。下面开始讲述这种面向连接的套接口信息发送与接收操作。

    用connect 函数连接到远程计算机以后,可以用 send 函数将应答信息发送给请求服务的本地主机,通信时双向的,并且通信的双方是对等的。

    send() 函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int send(int sockfd, const void*buf, int len, int flags);
函数传入值

sockfd:套接字描述符

buf:发送缓冲区的地址 入参

len:发送数据的长度

flags:一般为0

函数返回值

成功:实际发送的字节数

出错:-1

 

2)recv()函数

       函数recv 可以接收远程主机发送来的数据,并将这些数据保存到一个数组中,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int recv(int sockfd, const void*buf, int len, int flags);
函数传入值

sockfd:套接字描述符

buf:存放接收数据的缓冲区 出参

len:接收数据的长度

flags:一般为0

函数返回值

成功:实际接收的字节数

出错:-1


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php curl拉取远程图片

<?php $url "图片绝对地址/thumbnail.jpg"; $filename curl.jpg; getImg($url, $filename); /**通过curl方式获取制定的图片到本地* 完整的图片地址* 要存储的文件名*/ function getImg($url "", $filename "") {if(is_dir(basename($fi…

利用indent格式化源文件的脚本

脚本一&#xff1a;格式化指定目录下的源文件(*.h, *.cpp...) #!/bin/sh# 格式化某目录下所有*.h, *.c, *.cpp, *.hh文件, 并将文件换行符转换成Linux下的格式if [ $# -lt 1 ]; thenecho "Usage: $0 <dir>"exit 1elsedir$1fi# format a source file(*.c, *.h,…

Struts入门(三)深入Struts用法讲解

访问Servlet APIAction搜索顺序动态方法调用指定多个配置文件默认ActionStruts 后缀接收参数处理结果类型1.访问Servlet API 首先我们了解什么是Servlet API httpRequest、httpResponse、servletContext  3个api对应jsp面向对象&#xff1a;request、response、application …

Linux ALSA声卡驱动之四:Control设备的创建

声明&#xff1a;本博内容均由http://blog.csdn.net/droidphone原创&#xff0c;转载请注明出处&#xff0c;谢谢&#xff01; Control接口 Control接口主要让用户空间的应用程序&#xff08;alsa-lib&#xff09;可以访问和控制音频codec芯片中的多路开关&#xff0c;滑动控件…

jQuery 入门教程(5): 显示/隐藏内容

2019独角兽企业重金招聘Python工程师标准>>> jQuery的hide()和show()可以用来显示和隐藏内容。比如下面的例子&#xff1a;jQuery的hide()和show() 可以用来显示和隐藏内容。比如下面的例子&#xff1a; [html] view plain copy print ? <!doctype html> …

键盘键值表

键盘键值表 值 描述 0x1 鼠标左键 0x2 鼠标右键 0x3 CANCEL 键 0x4 鼠标中键 0x8 BACKSPACE 键 0x9 TAB 键 0xC CLEAR 键 0xD ENTER 键 0x10 SHIFT 键 0x11 CTRL 键 0x12 MENU 键 0x13 PAUSE 键 0x14 CAPS LOCK 键 0x1B ESC 键 0x20 SPACEBAR 键 0x21 PAGE UP 键 0x22 PAGE DOW…

Spring自动扫描配置及使用方法

2019独角兽企业重金招聘Python工程师标准>>> 首先&#xff0c;检查一下你lib下有没有 common-annotations.jar 这个jar包 没有的话要导入工程。 下一步配置spring的配置文件applicationContex.xml&#xff0c;加入命名空间 红色为需要添加的内容 <beans xmlns…

Linux下ln命令使用

n是linux中又一个非常重要命令&#xff0c;它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录&#xff0c;用到相同的文件时&#xff0c;我们不需要在每一个需要的目录下都放一个必须相同的文件&#xff0c;我们只要在某个固定的目录&#xff0c…

DPM 2012 SP1---安装并部署DPM 2012 SP1服务器

实验拓扑图&#xff1a;一、前提条件&#xff1a;需要在DPM2012 SP1服务器上完成以下操作&#xff1a;1.DPM服务器加入域&#xff08;使用域管理员登陆DPM2012 SP1服务器&#xff09;2.准备存储磁盘&#xff08;新添加一块硬盘&#xff09;3.关闭防火墙服务&#xff08;DPM服务…

Linux下test命令使用

test命令格式&#xff1a; [cpp] view plain copy test condition 通常&#xff0c;在if-then-else语句中&#xff0c;用[]代替&#xff0c;即[ condition ]。注意&#xff1a;方括号两边都要用空格。 1、数值比较 比 较 描 述 ---------------------------------------…

用Mysql网页式管理工具安全地访问数据库的方法

2019独角兽企业重金招聘Python工程师标准>>> 用Mysql网页式管理工具安全地访问数据库的方法 在使用通达OA系统时很多用户需要借助Mysql网页式管理工具进入后台数据库去查看数据&#xff0c;进行一些相应的操作。但是大多数时候用户安装完该工具后都是直接进入后台数…

Linux 下的DMA浅析

DMA是一种无需CPU的参与就可以让外设和系统内存之间进行双向数据传输的硬件机制。使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来&#xff0c;从而大大提高系统的吞吐率。DMA经常与硬件体系结构特别是外设的总线技术密切相关。 一、DMA控制器硬件结构 DMA允许外围设备…

从值栈中获取数据

使用struts2的标签ognl表达式获取值栈数据 <s:property value"ognl表达式"/> 一、获取字符串 示例 打印后台string变量的值 jsp页面 Java代码 二、获取对象 示例 打印user对象的userName与userPwd的值 jsp页面 java代码 三、获取list集合 Java代码 1.通过list[…

SQL 事务

事务的acid理解简介ACID&#xff0c;是指在可靠数据库管理系统&#xff08;DBMS&#xff09;中&#xff0c;事务(transaction)所应该具有的四个特性&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isola…

网络协议复习

不同协议所属的层次如下图&#xff1a; IP IP地址一开始是分类编址&#xff0c;到了20世纪90年代更换为无分类编址。分类编址时IP地址共有五类ABCDE。对于ABC类地址&#xff0c;IP地址都可以划分为网络标识和主机标识。从一个IP地址中提取网络地址要用网络掩码和IP地址进行与运…

CSDN-markdown编辑器使用手册

Markdown手册欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也…

Office 365身份认证管理-添加并验证联合认证域

首先需要安装MicrosoftOnlineServicesSign-inAssistant接受许可并安装安装完成接着安装WindowsAzureActiveDirectoryModuleforWindowsPowerShell安装程序启动接受许可设置安装路径开始安装安装完毕登陆并打开office365管理中心&#xff0c;选择添加一个域开始域添加向导输入我们…

codevs1040统计单词个数(区间+划分型dp)

1040 统计单词个数 2001年NOIP全国联赛提高组 时间限制: 1 s空间限制: 128000 KB题目等级 : 黄金 Gold题目描述 Description给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入&#xff0c;且保证每行一定为20个)。要求将此字母串分成k…

翻译词典推荐

前言 今天在看一个API&#xff0c;遇到一些生词不会&#xff0c;花了些时间在选择词典上面&#xff0c;做个总结。 我的经历 先说说我使用词典的经历吧&#xff1a; 无网络条件&#xff1a;首选金山词霸&#xff0c;词霸本身1G多安装包配合将近2G的词典包&#xff0c;即便是断网…