Linux网络编程之一
2015-10-10 10:55
417 查看
每日一结
一 网络基础知识
(一)IP地址
1.IP :网络中一台主机唯一标识
2.组成 :网络号 + 主机号
3.IP 分类
最高位 第一个字节
A 1 + 3 0 [0-127]
B 2 + 2 10 [128-191]
C 3 + 1 110 [192-223]
D 组播 1110 [224-239]
E 未使用
4.IP地址大小
IPv4 : 32bit->4byte IPv6 : 128bit->16byte
5.IP地址表示方法
点分十进制
(二)子网掩码 : 屏蔽主机号得到网络号
在发网络数据包的时候,我们会用: 目标IP & submask 获得网络号,判别目标主机和当前主机是否在同一个网段
如果在同一个网段 :数据包直接发走
如果不在同一个网段 :数据包发送到网关
(三)网关 : 负责向外网转发数据包
默认网关一般用路由器
(四)DNS : 域名解析服务器
域名->IP
www.baidu.com -> 百度IP
免费的域名:
8.8.8.8
114.114.114.114
二 一桢数据包格式
src mark,dest mark | src ip,dest ip |src port,dest port |data
-----------------------------------------------------------
<1>如何获得目标mark ?
ARP : IP->Mark
<2>必须知道的信息
目标IP和目标Port
<3>Port含义
Port端口号和进程绑定,目标主机收到数据包后根据它决定接受数据包的进程
注:百度一下数据包在网络中转发的详细过程
具体见文档
三 网络的体系结构 :网络的层次结构和每一层使用的协议集合
OSI模型[理想化模型]
应用层 : 准备数据
表示层 : 规定数据格式,加密和解密
会话层 : 建立连接
传输层 : 传输数据的协议
网络层 : 数据路由
数据链路层 : 组合成一祯数据包
物理层 : 二进制流
ICP/IP模型[实际使用]
应用层 : 准备数据 [http , ftp , tftp ...]
传输层 : 传输数据的协议[TCP,UDP]
网络层 : 数据路由 [IP,ICMP,IGMP,...]
物理接口层 : 组合成一祯数据包,然后发送 [ARP,RARP]
路由器工作在网络层
交换机工作在数据链路层
四 Linux 协议栈
应用层 数据 用户空间
-----------------------------------------------------------
传输层 TCP头/UDP头 + 数据 内核空间
网络层 IP头 + TCP头/UDP头 + 数据
数据链路层 Mark头 + IP头 + TCP头/UDP头 + 数据
五 TCP协议 和 UDP协议
协议:双方规定好的数据格式
1.TCP 协议特点
<1>面向连接 [三次握手]
建立连接
第一次:
Client send request to Server [标志SYN:1] [ClentSeqNum : 100]
第二次:
Server send request and ack to Client [标志SYN:1 ,ACK : 1] [ServerSeqNum : 200 ,AckNum:101]
第三次:
Client send ack to Server [标志ACK : 1] [ClentSeqNum : 101 ,AckNum : 201]
-----------------------------------------------------------
数据收发
Client发送数据
Client send data to Server
Server应答数据
Server send ack to Client
-----------------------------------------------------------
双方断开
四次挥手
<2>保证数据包可靠
数据无丢失,数据包无错误, 数据包无失序,数据无重复达到
TCP协议使用的产合:
发送邮件,数据下载,QQ登录 ...
2.UDP协议
<1>面向无链接
<2>不保证数据包可靠
UDP协议使用的产合:
QQ 聊天,多媒体数据传输 ...
六 字节序 (主机字节序)
不同的CPU字节序可能不一样
<1>大端模式
低地址存放高字节,高地址低字节
<2>小段模式
低地址存放低字节,高地址高字节
注意:网络中传输数据规定为网络字节序[大端模式]
七 字节序转换函数
1.IP字符串转换
<1>将IP字符串转成四个字节网络字节序
in_addr_t inet_addr(const char *cp);
功能:将cp指向的IP字符串转成网络字节序
返回值:
成功返回网络字节序,失败返回INADDR_NONE [0xffffffff]
BUG:无法识别IP地址255.255.255.255
int inet_aton(const char *cp, struct in_addr *inp);
功能:将cp指向的IP字符串转成网络字节序存放inp保存的地址中
参数:
@cp IP字符串首地址
@inp 存放网络字节序的地址
返回值:
成功返回非0,失败返回0
<2>将IP网络字节序转成IP字符串
char *inet_ntoa(struct in_addr in);
参数:
@in IP网络字节序
返回值:
成功返回IP字符串首地址,失败返回NULL
2.整数转换
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
代码示例如下:
其运行结果如下:
注:网络字节序和主机字节序有什么区别?
网络字节序:网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用大端(big endian)排序方式。
主机字节序:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序 。
八 UDP服务器和客户端实现
<1>创建套接字
int socket(int domain, int type, int protocol);
参数:
@domain 地址域 AF_UNIX[本地进程间通信] ,AF_INET [ IPv4 ]
@type 套接字类型 : 流式套接字 SOCK_STREAM[TCP] , 用户数据报套接字 SOCK_DGRAM[UDP]
原始套接字 SOCK_RAW
@protocol 协议编号 0:系统根据套接字类型自动识别协议 原始套接字:需要协议指定协议编号
返回值:
成功返回socket描述符,失败返回 -1
int sockfd;
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd < 0){
...
}
<2>给套接字指定IP和端口号
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
@sockfd 套接字
@addr 指定的地址
@addrlen 地址长度,struct sockaddr 结构体大小
通用地址结构:不好填充IP地址和端口
struct sockaddr
{
unsigned short sa_family;
char sa_data[14];
};
填充IP和Port结构体
struct sockaddr_in
{
unsigned short sin_family; //AF_INET
unsigned short sin_port ; //port
struct in_addr sin_addr; //ip
char _pad[8];
};
./server 192.168.0.110 8888
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) < 0)
{
...
}
<3>收发数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
参数:
@sockfd 套接字
@buf 数据存放的地址
@len 期望接受的数据长度
@flags 0:阻塞的方式接受
@src_addr 获取发送数据的主机地址
@addrlen 值结果参数[使用前必须初始化,初始化大小为结构体大小]
返回值:
成功返回实际接受的字节数,失败返回-1
例如:
int n;
char buf[1024];
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(struct sockaddr)
n = recvfrom(sockfd,buf,sizeof(buf) - 1,0,(struct sockaddr *)&peer_addr,&addrlen);
buf
= '\0';
printf("-------------------------------------------\n");
printf("Port : %d\n",ntohs(peer_addr.sin_port));
printf("Ip : %s\n",inet_ntoa(peer_addr.sin_addr));
printf("Mtxt : %s\n",buf);
printf("-------------------------------------------\n");
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
@sockfd 套接字
@buf 数据存放地址
@len 实际数据长度
@flags 0
@dest_addr 目标地址
@addrlen 地址大小
返回值:
成功返回0,失败返回-1
代码示例一如下:
client1.c
server1.c
代码分析如下:
代码示例二如下:
linklist.c
client2.c
server2.c
注:在示例二这个代码编译时,记得和linklist.c一起编译
亦即: gcc linklist.c server2.c -o server2
gcc linklist.c client2.c -o client2
代码分析如下:
服务器和客户端聊天
具体习题见图片
Server.c
client.c
注:查询一下,在kill()函数中,SIGUSR1有什么作用?
代码分析如下:
一些小知识:
根据信息的传送方向,串行通讯可以进一步分为单工,半双工和全双工三种。信息只能单向传送为单工,信息能双向传送但不能同时双向传送称为半双工,信息能够同时双向传送称为全双工。
关注微信公众号获取更多资讯
一 网络基础知识
(一)IP地址
1.IP :网络中一台主机唯一标识
2.组成 :网络号 + 主机号
3.IP 分类
最高位 第一个字节
A 1 + 3 0 [0-127]
B 2 + 2 10 [128-191]
C 3 + 1 110 [192-223]
D 组播 1110 [224-239]
E 未使用
4.IP地址大小
IPv4 : 32bit->4byte IPv6 : 128bit->16byte
5.IP地址表示方法
点分十进制
(二)子网掩码 : 屏蔽主机号得到网络号
在发网络数据包的时候,我们会用: 目标IP & submask 获得网络号,判别目标主机和当前主机是否在同一个网段
如果在同一个网段 :数据包直接发走
如果不在同一个网段 :数据包发送到网关
(三)网关 : 负责向外网转发数据包
默认网关一般用路由器
(四)DNS : 域名解析服务器
域名->IP
www.baidu.com -> 百度IP
免费的域名:
8.8.8.8
114.114.114.114
二 一桢数据包格式
src mark,dest mark | src ip,dest ip |src port,dest port |data
-----------------------------------------------------------
<1>如何获得目标mark ?
ARP : IP->Mark
<2>必须知道的信息
目标IP和目标Port
<3>Port含义
Port端口号和进程绑定,目标主机收到数据包后根据它决定接受数据包的进程
注:百度一下数据包在网络中转发的详细过程
具体见文档
三 网络的体系结构 :网络的层次结构和每一层使用的协议集合
OSI模型[理想化模型]
应用层 : 准备数据
表示层 : 规定数据格式,加密和解密
会话层 : 建立连接
传输层 : 传输数据的协议
网络层 : 数据路由
数据链路层 : 组合成一祯数据包
物理层 : 二进制流
ICP/IP模型[实际使用]
应用层 : 准备数据 [http , ftp , tftp ...]
传输层 : 传输数据的协议[TCP,UDP]
网络层 : 数据路由 [IP,ICMP,IGMP,...]
物理接口层 : 组合成一祯数据包,然后发送 [ARP,RARP]
路由器工作在网络层
交换机工作在数据链路层
四 Linux 协议栈
应用层 数据 用户空间
-----------------------------------------------------------
传输层 TCP头/UDP头 + 数据 内核空间
网络层 IP头 + TCP头/UDP头 + 数据
数据链路层 Mark头 + IP头 + TCP头/UDP头 + 数据
五 TCP协议 和 UDP协议
协议:双方规定好的数据格式
1.TCP 协议特点
<1>面向连接 [三次握手]
建立连接
第一次:
Client send request to Server [标志SYN:1] [ClentSeqNum : 100]
第二次:
Server send request and ack to Client [标志SYN:1 ,ACK : 1] [ServerSeqNum : 200 ,AckNum:101]
第三次:
Client send ack to Server [标志ACK : 1] [ClentSeqNum : 101 ,AckNum : 201]
-----------------------------------------------------------
数据收发
Client发送数据
Client send data to Server
Server应答数据
Server send ack to Client
-----------------------------------------------------------
双方断开
四次挥手
<2>保证数据包可靠
数据无丢失,数据包无错误, 数据包无失序,数据无重复达到
TCP协议使用的产合:
发送邮件,数据下载,QQ登录 ...
2.UDP协议
<1>面向无链接
<2>不保证数据包可靠
UDP协议使用的产合:
QQ 聊天,多媒体数据传输 ...
六 字节序 (主机字节序)
不同的CPU字节序可能不一样
<1>大端模式
低地址存放高字节,高地址低字节
<2>小段模式
低地址存放低字节,高地址高字节
注意:网络中传输数据规定为网络字节序[大端模式]
七 字节序转换函数
1.IP字符串转换
<1>将IP字符串转成四个字节网络字节序
in_addr_t inet_addr(const char *cp);
功能:将cp指向的IP字符串转成网络字节序
返回值:
成功返回网络字节序,失败返回INADDR_NONE [0xffffffff]
BUG:无法识别IP地址255.255.255.255
int inet_aton(const char *cp, struct in_addr *inp);
功能:将cp指向的IP字符串转成网络字节序存放inp保存的地址中
参数:
@cp IP字符串首地址
@inp 存放网络字节序的地址
返回值:
成功返回非0,失败返回0
<2>将IP网络字节序转成IP字符串
char *inet_ntoa(struct in_addr in);
参数:
@in IP网络字节序
返回值:
成功返回IP字符串首地址,失败返回NULL
2.整数转换
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
代码示例如下:
其运行结果如下:
注:网络字节序和主机字节序有什么区别?
网络字节序:网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用大端(big endian)排序方式。
主机字节序:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序 。
八 UDP服务器和客户端实现
<1>创建套接字
int socket(int domain, int type, int protocol);
参数:
@domain 地址域 AF_UNIX[本地进程间通信] ,AF_INET [ IPv4 ]
@type 套接字类型 : 流式套接字 SOCK_STREAM[TCP] , 用户数据报套接字 SOCK_DGRAM[UDP]
原始套接字 SOCK_RAW
@protocol 协议编号 0:系统根据套接字类型自动识别协议 原始套接字:需要协议指定协议编号
返回值:
成功返回socket描述符,失败返回 -1
int sockfd;
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd < 0){
...
}
<2>给套接字指定IP和端口号
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
@sockfd 套接字
@addr 指定的地址
@addrlen 地址长度,struct sockaddr 结构体大小
通用地址结构:不好填充IP地址和端口
struct sockaddr
{
unsigned short sa_family;
char sa_data[14];
};
填充IP和Port结构体
struct sockaddr_in
{
unsigned short sin_family; //AF_INET
unsigned short sin_port ; //port
struct in_addr sin_addr; //ip
char _pad[8];
};
./server 192.168.0.110 8888
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) < 0)
{
...
}
<3>收发数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
参数:
@sockfd 套接字
@buf 数据存放的地址
@len 期望接受的数据长度
@flags 0:阻塞的方式接受
@src_addr 获取发送数据的主机地址
@addrlen 值结果参数[使用前必须初始化,初始化大小为结构体大小]
返回值:
成功返回实际接受的字节数,失败返回-1
例如:
int n;
char buf[1024];
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(struct sockaddr)
n = recvfrom(sockfd,buf,sizeof(buf) - 1,0,(struct sockaddr *)&peer_addr,&addrlen);
buf
= '\0';
printf("-------------------------------------------\n");
printf("Port : %d\n",ntohs(peer_addr.sin_port));
printf("Ip : %s\n",inet_ntoa(peer_addr.sin_addr));
printf("Mtxt : %s\n",buf);
printf("-------------------------------------------\n");
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
@sockfd 套接字
@buf 数据存放地址
@len 实际数据长度
@flags 0
@dest_addr 目标地址
@addrlen 地址大小
返回值:
成功返回0,失败返回-1
代码示例一如下:
client1.c
server1.c
代码分析如下:
代码示例二如下:
linklist.c
client2.c
server2.c
注:在示例二这个代码编译时,记得和linklist.c一起编译
亦即: gcc linklist.c server2.c -o server2
gcc linklist.c client2.c -o client2
代码分析如下:
服务器和客户端聊天
具体习题见图片
Server.c
client.c
注:查询一下,在kill()函数中,SIGUSR1有什么作用?
代码分析如下:
一些小知识:
根据信息的传送方向,串行通讯可以进一步分为单工,半双工和全双工三种。信息只能单向传送为单工,信息能双向传送但不能同时双向传送称为半双工,信息能够同时双向传送称为全双工。
关注微信公众号获取更多资讯
相关文章推荐
- HTTP状态码
- 在ArcGIS中发布GoogleEarth瓦片为网络地图服务(wms)
- java中接口的定义与实现 http://blog.csdn.net/yjkwf/article/details/7238847
- RTP,RTCP,RTSP等网络协议有何用途和区别
- 基于mjpg-streamer网络视频服务器移植
- 《深入理解Linux网络技术内幕》阅读笔记(二十二)
- 关于 HTTP GET/POST 请求参数长度最大值的一个理解误区
- 解析虚拟VMware三种网络模式的根本区别
- C++接口实现总结 http://qimo601.iteye.com/blog/1393427
- http://www.google.com/ncr 谷歌无限制搜索方法,用过都说好
- tomcat+jdk的keytool生成证书 配置https
- TCP、UDP、IP 协议分析
- 网络流量监控命令-iftop
- https原理
- HttpClient_4 用法 由HttpClient_3 升级到 HttpClient_4 必看
- HttpClient 教程 (六)
- HttpClient 教程 (五)
- HttpClient 教程 (四)
- HttpClient 教程 (三)
- HttpClient 教程 (二)