Chinaunix首页 | 论坛 | 博客
  • 博客访问: 284804
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-27 08:37
个人简介

从linux了解世界

文章分类
文章存档

2017年(5)

2016年(51)

2015年(2)

我的朋友

分类: C/C++

2016-07-30 14:26:11

linux网络模型分四层:网络接口层(物理层,数据链路层),网络层,传输层,应用层(会话层,表示层,应用层)。括号内对应ios7层结构。
例如:以太网协议——ip——tcp——ftp逐层封装
以太网包:*目的地址和源地址

ip协议:ip的主要目的是为数据输入/输出网络提供基本算法,为高层协议提供无连接的传送服务。这意味着在ip将数据递交给接收站点以前不在传输站点和接受站点之间建立对话。他只是封装和传递数据,但不向发送者或接受者报告包的状态,不处理遇到的故障。*源ip和目的ip

tcp协议:tcp是重要的传输层协议,目的是允许数据同网络上的其他节点进行可靠的交换。他能提供断口编号的译码,以识别主机的应用程序,而且完成数据的可靠传输。具有严格的内装差错检验算法来确保数据的完成性。是面向字节的顺序协议,这意味着包内的每个字节被分配一个顺序编号,并分配给每包一个顺序编号。*源端口和目的端口

与tcp对应的udp协议:它是无连接的,不可靠的传输服务。当接收数据时塔不向发送方提供确认信息,它不提供输入包的顺序,如果发现丢失包或重份包的情况,也不会向发送方发出差错报文。由于它执行功能时具有较低的开销,因而执行速度比tcp快。


linux中的网络编程通过socket(套接字)实现,socket是一种文件描述符。
socket有三种类型:
流式套接字sock_stream:提供可靠的、面向连接的通讯流,使用tcp协议。tcp保证了数据传输的正确性和顺序性
数据报套接字sock_dgram:定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错,它使用数据报协议udp。
原始套接字sock_raw:使用ip协议,主要用于新的网络协议的测试。

socket程序设计中,struct sockaddr用于记录网络地址
struct sockaddr
{
    u_short sa_family;
    char sa_data[14];
}
sa_family:协议族,采用AF_xxx的形式如AF_INET(IP协议族)
sa_data:14字节的特定协议地址。
编程中一般使用与sockaddr等价的sockaddr_in数据结构,指向sockaddr_in的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,则可以在函数调用时将一个指向sockaddr_in的指针转换为指向sockaddr的指针。
struct sockaddr_in
{
    short int sin_family;协议族
    unsigned short int sin_port;端口号
    struct in_addr sin_addr;协议特定地址
    unsigned char sin_zero[8];填0
}
typedef struct in_addr
{
    union
    {
        struct
        {
            unsigned char s_b1,s_b2,s_b3,s_b4;
        }S_un_b;
        struct
        {
            unsigned short s_w1,s_w2;
        }S_un_w;
        unsigned long s_addr;记录ip地址
    }S_un;
}IN_ADDR;

基于tcp的服务器创建流程:
1创建socket
2绑定ip地址,端口等信息到socket上
3设置最大连接数
4等待客户端连接要求
5收发数据send和recv,read和write
6关闭网络连接
基于tcp的客户端创建流程:
1创建socket
2设置要连接的服务器ip地址和端口
3连接服务器
4收发数据
5关闭网络连接

进行socket编程的常用函数:socket创建一个socket;bind绑定ip地址和端口号到socket;connect连接服务器(udp不用);listen设置服务器处理的最大连接数;accept等待来自客户端的socket连接要求;send发送数据;recv接收数据;

int socket(int domain, int type, int protocol);如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET(Linux下失败返回-1)。
domain:协议域,又称协议族(family)。常用的协议族有AF_INET、 AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、AF_ROUTE等。协议族决定了socket的地址类型,在通信 中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地 址。
type:指定Socket类型。常用的socket类型有SOCK_STREAM、 SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一种 面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
protocol:指定协议。常用协议IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
注意:1.type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 指定一个套接字使用的地址和接口。addrlen是套接字地址接口的长度,可以使用sizeof(struct socketadd)。成功返回0,失败返回-1设置error,最常见为EADDRINUSER端口已被使用。

Int listen(int socket,int backlog)将socket创建的套接字由closed状态转换为listen状态,准备接受链接请求的信号,设定请求队列的长度。失败返回-1

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);响应连接请求,并产生一个新的socket描述符来描述该连接,用来与制定的客户端交换信息,函数调用返回之后向addr中填入远程连接过来的计算机信息,如ip和端口。addrlen表示addr所占内存区的大小,函数调用返回之后返回addr结构体的大小。默认为阻塞函数,一直阻塞直到有连接请求。执行成功,返回自动生成的新socket,失败返回-1设置errno。一般来说socket创建的用来侦听客户端链接请求,accept创建的用来数据通信。一个服务器一般只需要一个侦听套接字且一直存在,accept的套接字完成通信即可关闭,侦听套接字退出服务器才关闭。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);客户端用来连接服务器,成功返回0失败返回-1,设置errno。如果调用该函数前没有调用bind则不指定客户端的ip和端口,系统自动在1024到5000端口号选择一个并把本地ip和端口号填充到addr。调用成功后择可以使用sockfd作为与服务器连接的套接字描述符了,可以使用各种i/o函数。

ssize_t send(int sockfd, const void *buf, size_t len, int flags);len是信息buf的长度,函数返回实际发送长度,错误返回-1设置errno,flag一般为0.
ssize_t recv(int sockfd, void *buf, size_t len, int flags);同上

这两个函数用于udp无连接通信
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

void bzero(void *s, size_t n);s 要置零的数据的起始地址; n 要置零的数据字节个数。

int inet_aton(const char *cp, struct in_addr *inp);将192.163.1.1形式的ip转化为32位ip存储到inp指针中。如果这个函数成功,函数的返回值非零,如果输入地址不正确则会返回零。使用这个函数并没有错误码存放在errno中,所以它的值会被忽略。
char *inet_ntoa(struct in_addr in);将32位ip转化为192.163.1.1形式返回。

http://www.cnblogs.com/kerwinshaw/archive/2009/02/02/1382428.html define和typedef

网络字节顺序统一用big endian
       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);
在网络中标识一台主机可以用ip地址,也可以使用主机名。
Struct hostent *gethostbyname(const char *hostname)失败返回null并设置h_error错误变量,调用herror()可以得到对应错误变量的信息,成功返回一个结构体指针。
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);len一般为4,type一般为AF_INET。其他同上
Struct hostent
{
    char *h_name;主机的正式名称
    char *h_aliases;主机的别名
    int h_addrtype;主机的地址类型AF_INET
    int h_length;    主机的地址长度
    char **h_addr_list;主机的ip地址列表
}
#define h_addr h_addr_list[0]主机的第一个ip地址


阅读(1699) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~