全部包含:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/sctp.h>
#include <net/if.h>
#include <netdb.h>
tcp/ip协议有四层,ISO协议有七层;
应用层:
传输层:TCP,UDP,SCTP
网络层:IP,ICMP,IGMP
链路层:ARP,RARP
网络相关命令:
netstat
tcpdump
arp
lsof
iptables
ifconfig
ping
traceroute
route
在SVr4系统中编译函数要加链接库socket和nsl:
-lsocket -lnsl
编译sctp程序需要链接sctp库:
-lsctp
大端小端的问题
小端:低字节在起始地址,高字节在高地址
大端:高字节在起始地址,低字节在高地址
linux一般都是小端
unix一般都是大端
16位数据,由2个字节组成,一个字节在高地址,一个字节在低地址。
32位数据,由4个字节组成,以此类推。
ACK:acknowledgement,确认字符,接收站发给发送站的一种传输类控制字符。
FIN:表示发送结束,关闭连接
SYN:synchronize,握手信号
TCP:为用户进程提供可靠的字节流的全双工的面向连接的传输控制协议。
UDP:不可靠的无连接的用户数据报协议。
SCTP:提供可靠的全双工关联的面向连接的流控制传输协议。
下面的tcp和udp的套接字是传输层的API,由应用层调用;
应用层处于用户态;
传输层、网络层和链路层处于内核态。
socket函数都是posix标准的函数,
sctp是tcp和udp的升级版,尽量使用sctp的API
ipv6是ipv4的升级版,尽量使用Ipv6的API
使用tcp/ip协议的应用程序通常采用两种编程接口:
1. socket(BSD的socket接口)
2. TLI或XTI(传输接口, XTI是TLI的超集),现已不用.
###########################################################
网络编程相关库函数:
###########################################################
字节序转换库函数:
客户和服务程序在传输之前,需要将内部整数的表示方式转换成网络字节序。
unix的网络字节序一般是大端,linux的网络字节序一般是小端。
主机字节序十进制整数转换成网络字节序的短整型和长整型:
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
网络字节序转换成主机字节序的短整型和长整型:
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t htohl(uint32_t net32bitvalue);
16位处理端口
32位处理地址
----------------------
字节操纵库函数:
BSD:
#include <strings.h>
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t nbytes);
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
ANSIC:
#include <string.h>
void *memset(void *dest, int c, size_t len);
void *memcpy (void *dest, const void *src, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t ntbytes);
bzero和memset一般用来将套接字地址初始化为0.
----------------------
网际地址转换库函数:
在 ASCII字符串(点分十进制字符串,人们偏爱的格式)
和 网络字节序的二进制(存放在套接字地址中的值)
之间转换网际地址。
点分十进制(a)也叫表达(p)
网络字节序的二进制(n)也叫数值(n)
将点分十进制字符串转换成32位的网络字节序二进制ipv4地址:
int inet_aton(const char *strptr, struct in_addr *addrptr);
in_addr_t inet_addr(const char *strptr);//一般不再使用该函数
将32为的网络字节序二进制ipv4地址转换成点分十进制字符串:
char *inet_ntoa(struct in_addr inaddr);
同时适用于ipv4和ipv6的两个转换函数(现在一般用这个):
下面两个函数是可重入的。
将点分十进制字符串strptr转换成32位的网络字节序二进制地址addrptr:
int inet_pton(int family, const char *strptr, void *addrptr);
ipv4中void *一般为struct in_addr *也就是&sin_addr.
strptr一般是IP地址。
将32位的网络字节序二进制地址addrptr转换成点分十进制字符串strptr:
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_tlen);
family:
AF_INET //ipv4
AF_INET6 //ipv6
len:
#define INET_ADDRSTRLEN 16 //ipv4
#define INET6_ADDRSTRLEN 46 //ipv6
-----------------------------------------------------------
ipv4套接字地址结构:
typedef uint32_t in_addr_t; //32位无符号整数
typedef unsigned short int sa_family_t;
typedef uint16_t in_port_t;
struct in_addr //ipv4地址结构
{
in_addr_t s_addr; //32位二进制的ipv4地址
};
ipv4:
s_addr = htonl(INADDR_ANY);为0,这个通配地址常量为0,内核自己选择地址
struct sockaddr_in //ipv4网际套接字地址结构,一般定义这个变量
{
uint8_t sin_len; //linux 没有这个参数
sa_family_t sin_family; //AF_INET
in_port_t sin_port; //port number
struct in_addr sin_addr; //32 bit ipv4address
char sin_zero[8]; //unused
};
sin_addr.s_addr = htonl(INADDR_ANY);
sin_port = htons(SERV_PORT);
struct sockaddr //旧版本通用套接字地址结构,一般套接字函数用这个变量
{
uint8_t sa_len; // linux没有这个参数
sa_family_t sa_family;
char sa_data[14];
};
将struct sockaddr_in强转成struct sockaddr类型用在套接字api中。
这个是适用于ipv4的与协议无关的通用套接字地址结构。
-------------------------
ipv6套接字地址结构:
struct in6_addr //ipv6地址结构
{
uint8_t s6_addr[16]; //128位二进制的ipv6的地址
}
ipv6:
s_addr = htonl(IN6ADDR_ANY_INIT);
struct sockaddr_in6 //ipv6网际套接字地址结构
{
uint8_t sin6_len; //lenth of structure
sa_family_t sin6_family; //AF_INET6
in_port_t sin6_port; //port number
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr; //128 bit ipv6address
uint32_t sin6_scope_id;
}
struct sockaddr_storage //新的通用套接字地址结构
{
uint8_t sa_len;
sa_family_t sa_family;
….
}
这个是适用于ipv6的与协议无关的通用套接字地址结构。
原文:http://blog.csdn.net/wowotouweizi/article/details/43988823