LinuxC 网络编程(一)

来源:互联网 发布:电脑监控软件 编辑:程序博客网 时间:2024/06/04 23:33

LinuxC 网络编程(一)

@救世主JustPig 2016年8月14日 星期日

基于TCP/IP的服务端、客户端编写,本篇文章涉及TCP/IP编程的基础知识及编程模型。

## 字节序* 通用的网络协议中所使用的字节序为**大端字节序**。不同CPU及操作系统使用不同字节序来存储数据。* 无论你的机器体系结构是否与网络字节序相同,**最好都使用字节序转换将主机字节序转为网络字节序**。* 引入相关的库以使用字节序转换相关函数
#include <arpa/inet.h>

相关的数据结构

  • 使用Socket编程,有以下两种地址结构用以保存完整的网络协议信息

    1. 通用地址结构

      struct sockaddr{    unsigned short sa_family;   //地址族    char sa_data[14];           //协议信息};
    2. 因特网地址结构

      struct in_addr{    in_addr_t s_addr; //IP地址};struct sockaddr_in{    short int sin_family; //地址族(使用主机字节序)    unsigned short int sin_port; //16位端口值(使用网络字节序)    struct in_addr sin_addr; //IP地址(使用网络字节序)    unsigned char sin_zero[8]; //添0,格式对齐的填充位}
  • 两种结构体实际上完全等效,可以互相转换

  • 常常在定义时采用因特网地址结构,使用时强转位通用地址结构

地址族

IP协议是TCP/IP的核心协议,IPv4表示IP协议版本为4,而下一代IP协议则是IPv6。

  • 地址族常用的有AF_INET(IPv4)、AF_INET6(IPv6)两种。

    其中AF表示Address Family

协议族

协议族有基于传输层的TCP、UDP协议族、基于网络层(ip层)的协议族以及位于链路层的协议等。

  • 以下列出7种在SOCKET中定义的协议族的宏

    1. SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。2. OOB: 在所有数据传送前必须使用connect()来建立连接状态。3. SOCK_DGRAM: 使用不连续不可靠的数据包连接,基于UDP协议。4. SOCK_SEQPACKET: 提供连续可靠的数据包连接。5. SOCK_RAW: 提供原始网络协议存取。6. SOCK_RDM: 提供可靠的数据包连接。7. SOCK_PACKET: 与网络驱动程序直接通信。

相关函数

1. Socket

#include <sys/socket.h>

int socket(int domain,int type,int protocol)//      返回:成功返回对应的socket描述符,出错返回-1//      参数:domain: 一般选择AF_INET(IPv4协议)//      type: [SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、//              SOCK_SEQPACKET]//      protocol:   通常为0,表示按给定的域或套接字类型选择默认协议。//                  当对同一域和套接字类型支持多个协议时,可以使用//                  protocol参数选择一个特定协议int bind(int sockfd, const struct sockaddr* addr, socklen_t len);//      返回:成功0、错误-1//      功能:如上文//          查找绑定到套接字的地址:getsockname函数//          获取对方地址:getpeername函数//      int listen(int sockfd, int backlog);//      返回:成功0,错误-1//      参数:sockfd为套接字描述符、backlog为客户端队列长度int connect(int sockfd, const struct sockaddr* addr, socklen_t len);//      返回:成功0,错误-1//      参数:addr为服务器的地址结构指针。

2. 点分十进制地址与32位IPv4地址转换:

#include <arp/inet.h>

const char *inet_ntop(int domain,                     const void *restrict addr,                    char* restrict str,socklen_t size);//成功返回地址字符串指针,出错返回NULL。。//功能:网络子节序转换成点分十进制int inet_pton(int domain,const char *restrict str,void *restrict addr);//成功返回1,无效格式返回0,出错返回-1//功能:点分十进制转换为网络字节序//参数://  domain:地址族//  addr:IPv4地址(网络字节序)//  str:地址字符串(点分十进制)指针//  size:地址字符串大小

3. 主机字节序与网络字节序转换

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);uint16_t htons(uint16_t hostshort);uint32_t ntohl(uint32_t netlong);uint16_t ntohs(uint16_t netshort);//功能:   将一个32位整数由主机字节序转为网络字节序或相反//  h代表主机,n代表网络,l代表long,s代表short

编程模型

一. 服务端模型

1. 调用socket函数创建套接字2. 调用bind函数将套接字与本地地址、端口进行绑定3. 调用listen函数将socket的监听开启4. 调用accept从监听队列中获得客户端的请求fd5. 通过send、recv、write、read实现与客户端的IO通信6. 调用close关闭套接字

二. 客户端模型

1. 调用socket函数创建套接字2. 调用connect连接服务器(获得服务端fd)3. 调用send、recv、write、read实现与服务端的IO通信4. 调用close关闭套接字

相比服务端模型,客户端模型中,少了调用bind和listen的过程。