您的位置:首页 > 理论基础 > 计算机网络

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有什么作用?

 

代码分析如下:

 

 

一些小知识:

根据信息的传送方向,串行通讯可以进一步分为单工,半双工和全双工三种。信息只能单向传送为单工,信息能双向传送但不能同时双向传送称为半双工,信息能够同时双向传送称为全双工。

 

关注微信公众号获取更多资讯



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: