进程通信网络通信socket详细

网络模型:
OSI(Open System Interconnect):开放式系统互联 该网络模型分7层
物理层->数据链路层->网络层->传输层->会话层->表示层->应用层(底层->高层)
物理层:利用物理介质给数据链路层提供物理连接,以便透明的传输比特流.常见设备:网卡 网线
             对应的协议:(IEEE 802.1A,IEEE 802.2到IEEE 802.11)
数据链路层:在这层将数据分帧,为网络层提供数据链路的链接,在一条有可能出差错的物理连接上,
                    进行几乎无差错的数据传输,常见的设备:交换机 网桥
                    对应的协议:(FDDI,Ethernet,Arpanet,PDN,SLIP, PPP)
网络层:本层通过寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换
             节点,正确无误地按照地址传送给目的端的运输层,它包括通过互连网络来路由和中继数据,除了
             选择路由之外,网络层还负责建立和维护连接,控制网络上的拥塞以及在必要的时候生成计费信息.
             对应的协议:(IP,ICMP,ARP,RARP,AKP,UUCP)
传输层:常规数据递送-面向连接或无连接,为会话层用户提供一个端到端的可靠透明和优化的数据传输
            服务机制.包括全双工或半双工.流控制和错误恢复服务;传输层把消息分成若干个分组,并在接收
            端对它们进行重组.不同的分组可以通过不同的连接传送到主机.这样既能获得较高的带宽,又不
            影响会话层,建立连接时传输层可以请求服务质量,该服务质量指定可接受的误码率.延迟量.安全
            性等参数,还可以实现基于端到端的流量控制功能。
            对应的协议:(TCP UDP 协议)
会话层:在两个节点之间建立端连接,为端系统的应用程序之间提供了对话控制机制,此服务包括建立连接
            是以全双工还是以半双工的方式进行设置,尽管可以在层4中处理双工方式;会话层管理登入和注
            销过程.它具体管理两个用户和进程之间的对话.如果在某一时刻只允许一个用户执行一项特定的
            操作,会话层协议就会管理这些操作,如阻止两个用户同时更新数据库中的同一组数据.
            对应的协议:(SMTP, DNS)
表示层:主要用于处理两个通信系统中交换信息的表示方式,为上层用户解决用户信息的语法问题,它包括
             数据格式交换.数据加密与解密.数据压缩与终端类型的转换.
             对应的协议:(Telnet, Rlogin, SNMP, Gopher)
应用层:应用层确定进程之间通信的性质,以满足用户的需要.应用层不仅要提供应用进程所需要的信息交
            换和远程操作,而且还要作为应用进程的用户代理,来完成一些为进行信息交换所必需的功能.它包
            括:文件传送访问和管理FTAM.虚拟终端VT.事务处理TP.远程数据库访问RDA.制造报文规范MMS.目
            录服务DS等协议;应用层能与应用程序界面沟通,以达到展示给用户的目的.
            对应的协议:(HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等.)
   
TCP/IP网络模型:该模型分4层
数据链路层->网络层->传输层->应用层(底层->高层)
 

socket结构体:(在netinet/in.h中定义):
struct sockaddr_in
{ 
   short int sin_family;  //地址协议族
   unsigned short int sin_port; //端口号1024-65535 小于1024的端口号都被系统保留 网络字节序
   struct in_addr sin_addr;  //存储IP地址 网络字节序
   unsigned char sin_zero[8]; //是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
}; 

struct sockaddr
{ 
   unsigned short sa_family;
     char sa_data[14];  
};

struct in_addr {
unsigned long s_addr;
};
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;
          } S_un;
} IN_ADDR;
sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序)
sin_addr存储IP地址,使用in_addr这个数据结构
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
s_addr按照网络字节顺序存储IP地址
sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向
sockadd的结构体,并代替它.也就是说,你可以使用sockaddr_in建立你所需要的信息.



字节序处理:
网络字节顺序(NBO,Network Byte Order):TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型.
操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释,大端存储方式.
主机字节顺序(HBO,Host Byte Order):不同的机器HBO不相同,与CPU设计有关,分一下两种:
小端存储(Little endian):低序字节存储在起始地址(低地址)
大端存储(Big endian):高序字节存储在起始地址(低地址)
eg:将0x1234abcd写入到以0x0000开始的内存中,则结果为
address  big-endian    little-endian
0x0000   0x12          0xcd
0x0001   0x34          0xab
0x0002   0xab          0x34
0x0003   0xcd          0x12
x86系列CPU都是little-endian的字节序.

htons();将整型变量从主机字节顺序转变成网络字节顺序
原型:u_short htons(u_short hostshort);
参数:u_short hostshort 16位无符号整数
返回值:TCP/IP网络字节顺序.

htonl();将整型变量从主机字节顺序转变成网络字节顺序
原型:uint32_t htonl(uint32_t hostlong);
参数:uint32_t hostlong 32位无符号整数
返回值:TCP/IP网络字节顺序.

ntohs();网络字节顺序转换为主机字节顺序
原型:uint16_t ntohs(uint16_t netshort);
参数:uint16_t netshort 以网络字节顺序表达的16位数
返回值:以主机字节顺序表达的数

ntohl();网络字节顺序转换为主机字节顺序
原型:uint32_t ntohl(uint32_t netlong);
参数:uint32_t netlong 以网络字节顺序表达的32位数
返回值:以主机字节顺序表达的数

IP地址处理方式:
inet_addr是一个计算机函数,功能是将一个点分十进制的IP转换成一个长整数型数
原型:in_addr_t inet_addr(const char* strptr);
返回值:若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
struct in_addr{
in_addr_t s_addr;
}//in_addr_t在上边的结构体中对应unsigned long无符号长整型
eg:
struct sockaddr_in seraddr;
seraddr.sin_addr.s_addr = inet_addr("192.168.1.168");//已经转变为网络字节序,不用调用htonl了.

inet_ntoa()将网络字节序IP转化点分十进制IP
原型:char *inet_ntoa (struct in_addr);
返回值:返回点分十进制的字符串在静态内存中的指针.所以每次调用,将覆盖上次调用时所得的IP地址.

inet_aton是一个计算机函数,功能是将一个字符串IP地址转换为一个32位的网络序列IP地址
原型:int inet_aton(const char *string, struct in_addr*addr);
返回值:如果这个函数成功,函数的返回值非零,如果输入地址不正确则会返回零.
参数:输入参数string包含ASCII表示的IP地址,输出参数addr是将要用新的IP地址更新的结构.

int socket(int domain, int type, int protocol); 
参数:domain一般为AF_INET(IPv4 网络协议的套接字类型),其他参考资料
  type一般为SOCK_STREAM(提供面向连接的稳定数据传输,即TCP协议),其他参考资料
  protocol一般为0
返回值:成功返回套接字描述符,失败返回-1

int bind(int sockfd, struct sockaddr *my_addr, int addrlen); 
参数:sockfd为系统调用socket返回的套接字描述符
  my_addr为struct sockaddr类型的指针(保存端口信息和ip地址)
  addrlen为struct sockaddr类型的长度(sizeof(struct sockaddr))
返回值:成功返回0,失败返回-1.

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); 
参数:sockfd为系统调用socket返回的套接字描述符
  serv_addr是保存着目的地端口和IP地址的数据结构struct sockaddr
  addrlen为struct sockaddr类型的长度(sizeof(struct sockaddr))
返回值:成功返回0,失败返回-1.

int listen(int sockfd, int backlog); 
参数:sockfd为系统调用socket返回的套接字描述符
  backlog是允许连接的数量(多数系统允许连接的最大为20)
返回值:无错误,返回0,否则,返回SOCKET ERROR,可以调用函数WSAGetLastError取得错误代码.

int accept(int s, struct sockaddr * addr, int * addrlen);
参数:参数s的socket必需先经bind()listen()函数处理过
  addr为struct sockaddr类型的指针(请求者的结构体)
  addrlen为struct sockaddr类型的长度(sizeof(struct sockaddr))
返回值:成功返回一个新的套接字描述符,失败返回-1

int send(int sockfd, const void *msg, int len, int flags); 
参数:参数sockfd必需先经bind()listen()函数处理过
  msg为待发送数据的缓冲区
  len为缓冲区长度
  flags为处理的方式
返回值:成功返回实际发送的字数,失败返回-1.

int recv(int sockfd, void *buf, int len, unsigned int flags);类似上边
参数:参数sockfd为要读取的套接字描述符由accept返回
  msg为待接收数据的缓冲区
  len为缓冲区长度
  flags为处理的方式
返回值:成功返回实际接收的字数,失败返回-1.

int sendto(int sockfd, const void *msg, int len, unsigned int flags, 
    const struct sockaddr *to, int tolen); 
参数:
sockfd:一个标识套接口的描述字
buf:包含待发送数据的缓冲区
len:buf缓冲区中数据的长度
flags:调用方式标志位
to:(可选)指针,指向目的套接口的地址
tolen:to所指地址的长度
返回值:
若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小),否则的话,
返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码

int recvfrom(int sockfd, void *buf, int len, unsigned int flags,  
    struct sockaddr *from, int *fromlen);
参数:
s:标识一个已连接套接口的描述字
buf:接收数据缓冲区
len:缓冲区长度
flags:调用操作方式
from:(可选)指针,指向装有源地址的缓冲区
fromlen:(可选)指针,指向from缓冲区长度值
返回值:
若无错误发生,recvfrom()返回读入的字节数.如果连接已中止,返回0.否则的话,
返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码

close(sockfd);
int shutdown(int sockfd, int how); 
参数:sockfd是要关闭的套接字描述符,how是方式,0不接收,1不发送,2不接收和发送(等于close)

struct hostent * gethostbyaddr(const char * addr, socklen_t len, int family);
struct hostent {
char * h_name;
char * * h_aliases;
short h_addrtype;
short h_length;
char * * h_addr_list;
};
参数:
addr:指向网络字节顺序地址的指针
len:地址的长度,在AF_INET类型地址中为4
type:地址类型,应为AF_INET

int PASCAL FAR gethostname(char FAR *name, int namelen);
name:一个指向将要存放主机名的缓冲区指针
namelen:缓冲区的长度
返回本地主机的标准主机名([root@libmaster home]主机名为libmaster)

struct hostent *gethostbyname(const char *hostname);
hostname:指向主机名的指针
成功返回如上所述的一个指向hostent结构的指针,失败返回一个空指针
 

猜你喜欢

转载自blog.csdn.net/linuxzhuxiaodi/article/details/78601846