牙科医院网站建设方案,网站实名审核中心,温州 建网站的公司 新,网站推广seo教程互联网地址
每一台设备接入互联网后#xff0c;都会举报一个唯一的地址编号
IP地址 INTERNET地址
internet地址 #xff1a;它是协议上的一个逻辑地址
目前来说#xff0c;我们主要的IP地址有两类 IPV4 IPV6
IPV4 其实就是使用一个32bit整数作为IP
IPV6 其实就是使用一…互联网地址
每一台设备接入互联网后都会举报一个唯一的地址编号
IP地址 INTERNET地址
internet地址 它是协议上的一个逻辑地址
目前来说我们主要的IP地址有两类 IPV4 IPV6
IPV4 其实就是使用一个32bit整数作为IP
IPV6 其实就是使用一个128bit整数作为IP
ipv4
1010 1100 0000 0010 0000 0001 0000 0001 人类是看不到的
172.2.1.1 给人看的点分式
每8bit组成一个十进制数以 ‘.’ 隔开
2^32 个地址
这么多地址怎么去管理
类似电话号码 区号主机号
86 0731 12345678
86 中国大陆
0731 长沙
12345678 具体那个电话的号码
同理ip地址也分为两个部分
ip地址网络号主机号
网络号用于标识网络中的某个子网占ip地址中的高x位
主机号用于标识同一个子网内的不同主机占地址中低的(32-x)位
也叫做 子网号 子网主机号
所占的bit位x又怎么确定呢
netmask 子网掩码用来确定一个ip地址中网络号与主机号的占比
IP地址的bit位在子网掩码中对应的bit为1就是网络号
在子网掩码中为0就是主机号
比如
ip 172.2.1.1
netmask 255.255.255.0
网络号 ipnetmask 172.2.1.0
主机号的范围 172.2.1.0 ~ 172.2.1.255
目前ip地址主要分为5类 我们常用的是C类网络
端口号
在网络中可以提供ip地址来区分不同的网络设备
如果两个设备的IP相同 —》ip冲突只有一台能够接入网络
问题;一台设备上或许会运行多个网络应用
比如我打开QQ给你们传文件同时还在直播上课
那么网络中怎么知道传递的数据是由哪个网络应用发起的呢
ip只能区分是那一台主机不能区分是那一个应用
为了区分哪个网络应用传输的数据需要用到端口号
TCP和UDP都是采用16bit无符号整数来作为端口号标识网络应用
IP —标识网络中的某个设备
端口 —》标识设备上的某个网络应用
一台主机上的网络应用由
ip地址传输层协议TCP/UDP端口号来确定
端口号 由 IANS 来管理
1-1023 众所周知的端口
比如 HTTP应用 80
FTP服务 20
…
1024-49151 注册端口提供注册端口
49151-65536 动态或者私有端口可以随便用
字节序
大端模式
高地址存储低字节 低地址存储高字节
小端模式
低地址存储低字节 高地址存储高字节
比如 int a 0x12345678
a 0x4000
内存地址大端模式存储内容小端模式存储内容0x40000x120x780x40010x340x560x40020x560x340x40030x780x12
不同的系统对于内存的管理方法不同可能采用大端模式可能采用小端模式
练习尝试写一个程序判断自己的Linux系统是大端模式还是小端模式并且输出结果
int a 1; //0x00 00 00 01
char *p a
if(*p 1)
{printf(小端模式\n);
}
else
{printf(大端模式\n);
}网络字节序采用的是大端模式
网络接口 socket
网络通信接口 socket是一个简单易上手功能强大的接口
有以下特点
1.socket是一个编程接口网络编程接口
所有的网络程序都需要基于socket
2.socket也是一个特殊的文件描述符
特殊可以利用系统文件接口
比如 read write close
但是不能用lseek
它的内容不在文件系统中也不在内核中而是在网络中
3.socket 是TCP/IP协议的一种代码实现
但是它不仅限于TCP/IP协议它还支持蓝牙协议wifi协议,unix域协议
socket独立于具体协议的网络程序接口位于应用层与传输层之间负责衔接应用层与传输层
网络通信
网络通信的实现—》 API应用程序编程接口
1.socket 创建一个套接字
2.bind 不动将一个地址网络应用地址IP传输协议端口与套接字绑定
3.listen 监听用于设定服务器监听套接字监听后就可以获得客户端的请求
4.accpet 等待连接请求的到来
5.connect 用于发起连接请求
6.通信 数据收发
read/write
recv/send
recefrom/send_to
7.关闭套接字
close 套接字也就是一个文件描述符罢了
思考 在网络通信在服务器和客户端 双方的通信流程图 1 socket
NAMEsocket - create an endpoint for communicationSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hsocket用来创建一个通信接口int socket(int domain, int type, int protocol);domain指定域协议族AF_UNIX, AF_LOCAL Local communication unix(7)unix域协议/本地协议栈AF_INET IPv4 Internet protocols ip(7)IPV4协议族AF_INET6 IPv6 Internet protocols ipv6(7)IPV6协议族type指定套接字类型选择传输层协议SOCK_STREAM 流式套接字面向TCP传输层协议SOCK_DGRAM 数据报套接字面向UDP传输层协议SOCK_RAW 原始套接字protocol协议指定具体那个协议一般为0表示默认返回值成功返回一个整数是一个套接字文件描述符失败返回-1并且errno被设置2 bind
用于绑定服务器地址IP传输层协议端口号
NAMEbind - bind a name to a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hbind 绑定一个名字”给socket套接字描述符int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);sockfd指定套接字描述符就是socket的返回值addr:指向struct sockaddr 结构体指针保存的是要绑定的地址addrlen:地址长度即参数addr的长度sizeof (struct sockaddr)返回值成功返回0失败返回-1并且errno被设置关于网络应用的地址 IP传输层协议端口号
在 头文件sys/socket.h中定义了一个通用的网络应用地址结构体
struct sockaddr {sa_family_t sa_family;//指定协议栈和socket函数的参数domain相同char sa_data[14];//数组保存网络应用地址IP传输层协议端口号}上面这个结构体并不是很好赋值和使用一般在网络编程中网络应用地址赋值可以采用定义在
/usr/include/netinet/in.h中的结构体 struct sockaddr_in
Structure describing an Internet socket address
以太网地址结构体
struct sockaddr_in{__SOCKADDR_COMMON (sin_);//协议栈 sin_familyin_port_t sin_port; /* 端口号网络上一般是大端模式计算机一般是小端模式 */struct in_addr sin_addr; /* 指定ip地址. typedef uint32_t in_addr_t;struct in_addr{in_addr_t s_addr;};*//* Pad to size of struct sockaddr. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};eg:某个网络应用
ip 172.2.1.11
端口 6666
struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_familyAF_INET;//协议族
addr.sin_port htons(6666);//端口号是网络字节序短整型
addr.sin_addr.s_addr inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret 0;//返回值
ret bind(sockfd,(struct sockaddr)addr,sizeof(addr));
if(ret -1)
{perror(bind error);return -1;
}
//bind 之后进程就有了一个网络应用地址能够进行网络通信端口本地字节序转网络字节序
h host 主机
to 转换成
n network 网络
s short 16bit
l long 32bit
NAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte orderSYNOPSIS#include arpa/inet.huint32_t htonl(uint32_t hostlong);将本地字节序转换成网络长整型uint16_t htons(uint16_t hostshort);将本地字节序转换成网络短整型uint32_t ntohl(uint32_t netlong);将网络字节序转换成本地长整型uint16_t ntohs(uint16_t netshort);将网络字节序转换成本地短整型参数就是需要转换的数据返回值就是转换之后的数据点分式ip与32bit ip的转换
NAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routinesSYNOPSIS#include sys/socket.h#include netinet/in.h#include arpa/inet.hinet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回in_addr_t inet_addr(const char *cp);cp 指针指向要转换的点分式字符串ip成功返回转换后的32bit整数网络通信
网络通信的实现—》 API应用程序编程接口
1.socket 创建一个套接字
2.bind 不动将一个地址网络应用地址IP传输协议端口与套接字绑定
3.listen 监听用于设定服务器监听套接字监听后就可以获得客户端的请求
4.accpet 等待连接请求的到来
5.connect 用于发起连接请求
6.通信 数据收发
read/write
recv/send
recefrom/send_to
7.关闭套接字
close 套接字也就是一个文件描述符罢了
思考 在网络通信在服务器和客户端 双方的通信流程图 1 socket
NAMEsocket - create an endpoint for communicationSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hsocket用来创建一个通信接口int socket(int domain, int type, int protocol);domain指定域协议族AF_UNIX, AF_LOCAL Local communication unix(7)unix域协议/本地协议栈AF_INET IPv4 Internet protocols ip(7)IPV4协议族AF_INET6 IPv6 Internet protocols ipv6(7)IPV6协议族type指定套接字类型选择传输层协议SOCK_STREAM 流式套接字面向TCP传输层协议SOCK_DGRAM 数据报套接字面向UDP传输层协议SOCK_RAW 原始套接字protocol协议指定具体那个协议一般为0表示默认返回值成功返回一个整数是一个套接字文件描述符失败返回-1并且errno被设置2 bind
用于绑定服务器地址IP传输层协议端口号
NAMEbind - bind a name to a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hbind 绑定一个名字”给socket套接字描述符int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);sockfd指定套接字描述符就是socket的返回值addr:指向struct sockaddr 结构体指针保存的是要绑定的地址addrlen:地址长度即参数addr的长度sizeof (struct sockaddr)返回值成功返回0失败返回-1并且errno被设置关于网络应用的地址 IP传输层协议端口号
在 头文件sys/socket.h中定义了一个通用的网络应用地址结构体
struct sockaddr {sa_family_t sa_family;//指定协议栈和socket函数的参数domain相同char sa_data[14];//数组保存网络应用地址IP传输层协议端口号}上面这个结构体并不是很好赋值和使用一般在网络编程中网络应用地址赋值可以采用定义在
/usr/include/netinet/in.h中的结构体 struct sockaddr_in
Structure describing an Internet socket address
以太网地址结构体
struct sockaddr_in{__SOCKADDR_COMMON (sin_);//协议栈 sin_familyin_port_t sin_port; /* 端口号网络上一般是大端模式计算机一般是小端模式 */struct in_addr sin_addr; /* 指定ip地址. typedef uint32_t in_addr_t;struct in_addr{in_addr_t s_addr;};*//* Pad to size of struct sockaddr. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};eg:某个网络应用
ip 172.2.1.11
端口 6666
struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_familyAF_INET;//协议族
addr.sin_port htons(6666);//端口号是网络字节序短整型
addr.sin_addr.s_addr inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret 0;//返回值
ret bind(sockfd,(struct sockaddr)addr,sizeof(addr));
if(ret -1)
{perror(bind error);return -1;
}
//bind 之后进程就有了一个网络应用地址能够进行网络通信端口本地字节序转网络字节序
h host 主机
to 转换成
n network 网络
s short 16bit
l long 32bit
NAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte orderSYNOPSIS#include arpa/inet.huint32_t htonl(uint32_t hostlong);将本地字节序转换成网络长整型uint16_t htons(uint16_t hostshort);将本地字节序转换成网络短整型uint32_t ntohl(uint32_t netlong);将网络字节序转换成本地长整型uint16_t ntohs(uint16_t netshort);将网络字节序转换成本地短整型参数就是需要转换的数据返回值就是转换之后的数据点分式ip与32bit ip的转换
NAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routinesSYNOPSIS#include sys/socket.h#include netinet/in.h#include arpa/inet.hinet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回in_addr_t inet_addr(const char *cp);cp 指针指向要转换的点分式字符串ip成功返回转换后的32bit整数3 listen
设置监听用于监听网络上是否有客户端向“我”服务器发起链接请求
NAMElisten - listen for connections on a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hint listen(int sockfd, int backlog);sockfd:指定要监听的套接字描述符backlog:监听数量大于0就行了返回值成功返回0 失败返回-1并且errno被设置listen设置去监听套接字描述符以便知道是否有人(客户端)向我(服务器)发起链接请求
但是listen只监听不处理链接
Eg:
int ret 0;
ret listen(sockfd,10);
if (ret -1)
{perror(listen error);
}4 accept
用于等待链接请求并且处理链接请求
accpet会阻塞进程的运行直到客户端向服务器发起了链接请求客户端调用了connect)
NAMEaccept, accept4 - accept a connection on a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hint accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd:指定套接字描述符addr:指向struct sockaddr 结构体空间地址用于存储客户端的地址addrlen:指socklen_t空间地址addrlen参数在使用前需要先赋值 参数addr的长度因为在函数内部会先利用addrlen的值来确保捕获导致内存溢出返回值成功返回一个非负数该值是一个文件描述符》链接套接字描述符用于 服务器与链接的客户端的通信接口也就是说服务器是提供accept的返回值 来收发客户端的消息失败 返回-1并且errno被设置eg:
struct sockaddr_in caddr;//用于保存客户端的地址
socklen_t caddr_len sizeof(caddr);//保存客户端地址长度使用前保存该地址空间的长度
int connfd 0;//用于保存 链接套接字描述符
connfd accept(sockfd,(struct sockaddr*)caddr,$caddr_len);
if(connfd -1)
{perror(accept error);return -1;
}如果accept指向成功则connfd就是服务器与客户端之间的通信接口
如果我们是多次调用accept那么九年允许多个客户端连接并且每个客户端连接上来后
服务器上都有一一对应的connfd
5 connect
用于客户端向服务器发起链接请求
NAMEconnect - initiate a connection on a socketSYNOPSIS#include sys/types.h /* See NOTES */#include sys/socket.hint connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);sockfd:指定套接字描述符addr:指定要连接的服务器的地址addrlen:addr的长度返回值成功返回0失败返回-1并且errno被设置客户端调用 connect发起连接请求后服务器的acceot接收到连接请求并返回一个connfd用于服务器与客户端的通信接口
此时客户端写入/发送数据给sockfd的数据就会通过网络传递给服务器的connfd
服务器就可以从connfd中读取/接收 这些数据
eg:
int ret 0;
struct sockaddr_in saddr;
saddr.sin_familyAF_INET;//IPV4协议族
saddr.sin_port htons(6666);//端口号是网络字节序短整型
saddr.sin_addr.s_addr inet_addr(172.2.1.110);//客户端的ip
ret connect(sockfd,(struct sockaddr*)saddrsizeof(saddr));
if (ret -1)
{perror(connect error);return -1;
}6 数据收发
1 read/write
socket的网络通信其利用的是文件描述符符合Linux的设计哲学
2 recv/send 接收/发送
recv 结束
NAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include sys/types.h#include sys/socket.hrecv用于从指定的套接字描述符中接收数据同read)ssize_t recv(int sockfd, void *buf, size_t len, int flags);sockfd:指定套接字描述符即从那个接收输入buf:指向一块缓存区用于存储接收到的数据len指定要接收的字节数flags:接收标志位0 默认接收带阻塞接收如果能接收到数据就接收数据如果不能接收到数据就一直等待直到接收到数据MSG_DONTWAIT 不阻塞接收如果能够接收到数据则接收数据如果不能接收到数据则直接返回返回值0 成功返回实际接收到的字节数0 什么都没有接收到-1 接收失败并且errno被设置send 发送
NAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include sys/types.h#include sys/socket.hsend 用于向套接字描述符中发送数据ssize_t send(int sockfd, const void *buf, size_t len, int flags);sockfd:指定套接字描述符即发送到那里去buf:指向要发送的数据len:要发送的数据大小单位字节flags:发送标志位0 阻塞发送MSG_DONTWAIT 非阻塞发送返回值 成功返回实际发送的字节数(0)失败返回-1 并且errno被设置3 recvfrom/sendto
从哪里接收/发送给谁
特点
recvfrom 可以保存是谁发送过来的数据保存发送者的地址
sendto 可以指定发送的对象地址定向发送
一般用于UDP通信很少使用在TCP通信中WHY?
因为TCP面向连接的通信在通信前就已经要求通信双方建立连接
UDP是非连接的通信所以他需要指定发送给谁要保留发送者的地址
recvfrom
NAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include sys/types.h#include sys/socket.hssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);前面四个参数 同recvsrc_addr:指向一个 struct sockaddr缓存区地址用于存储对方的地址addrlen:指向一个 socklen_t缓存区地址用于存储对方地址的长度src_addr和addrlen的使用参考accept函数sendto
NAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include sys/types.h#include sys/socket.hssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);前四个参数 同senddest_addr指向一个 struct sockaddr缓存区地址表示发送给谁addrlen即dest_addr的长度4 recvmsg/sendmsg
以结构体的形式 发送数据/接收数据
7 关闭套接字
套接字 socket 套接字描述符
服务器用于监听看是否有客户端发起连接请求
客户端用于客户端与服务器的通信接口
close 关闭套接字
shutdown
NAMEshutdown - shut down part of a full-duplex connectionSYNOPSIS#include sys/socket.hshutdown用于关闭一个链接通道int shutdown(int sockfd, int how);sockfd:指定套关闭那个链接通道how:怎样关闭SHUT_RD 关闭读SHUT_WR 关闭写SHUT_RDWR 关闭读写返回值成功返回0失败返回-1并且errno被设置eg:我们搭建的服务器只获取客户端的信息而不用给客户端发送信息
则可以关闭链接套接字的写功能
shutdown(connfd,SHUT_WR); //connfd 就变成了只读结合已有函数和示例代码查看流程图
尝试搭建一个TCP服务器
create_tcpserver 创建TCP服务器 1 创建socket套接字 网络通信接口 2 bind 绑定网络应用地址便于其他应用找到本程序的通信接口 3 listen 设置监听内核监听是否有客户端向服务器发起连接请求 mian 1 创建服务器 create_tcpserver 2 等待客户端的连接请求并于客户端建立连接 accept的返回值connfd就是一个用来与客户端通信的描述符 链接套接字描述符 3 根据需求编写与客户端的通信 案例实现Ubuntu与开发板互相通信
点此跳转查看案例源码