套接字的地址结构,IP地址转换函数,网络编程的接口

一、套接字的地址结构
我们前面所讨论的IPC机制都依靠一台计算机系统的共享资源实现,这里的资源可以是文件系统空间,共享的物理内存或者消息队列,但只有运行在同一台机器上的进程才能使用它们.

一台机器上的进程可以使用套接字和另外一台机器上的进程通信,这样就可以支持分布在网络中的客户/服务器系统.

同一台机器上的进程之间也可以使用套接字进行通信,

套接字的特性由3个属性确定,它们是:域(domain),类型(type)和协议(protocol).

套接字用地址作为它的名字,地址的格式随域(又被称为协议族,protocol family)的不同而不同,每个协议族又可以使用一个或多个地址族来定义地址格式,

1.1 通用socket地址结构
socket 网络编程接口中表示 socket 地址的是结构体 sockaddr,其定义如下:

#include <bits/socket.h>
struct sockaddr
{
    sa_family_t sa_family;//协议族
    char sa_data[14];//数据,没有给出IP地址,就是给了这么一块儿空间,起了一个占位的作用。
};
sa_familvy 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族和对应的地址族如下图所示:

1.2 专用socket地址结构
TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用 socket 地址结构体,它们分别用于 IPV4 和 IPV6:

sin_family:地址族 AF INET
sin_port:端口号,需要用网络字节序表示
sin_addr:IPV4 地址结构:s_addr 以网络字节序表示 IPV4 地址
struct in_addr
{
    u_int32_t s_addr;//无符号的32位的整型,存放IP地址;
};
1.2.1 tcp协议族
tcp协议族主要有三个:

地址族
端口号
IP地址
//tcp协议族
struct sockaddr_in
{
    sa_family_t sin_family;//地址族,就是sin_family:地址族 AF_INET
    u_int16_t sin_port;//端口,16位的端口
    struct in_addr sin_addr;//一个结构体,只有一个成员,是无符号的32位的整型,存放IP地址;(IPV4的地址就是32位)
    //其实后面还有占位的,只是我们不用它,所以就没有写
};
 
1.2.3 IP协议族
//IP协议族
struct in6_addr
{
    unsigned char sa_addr[16];// IPV6 地址,要用网络字节序表示
};
 
struct sockaddr_in6
{
    sa_family_t sin6_family;//地址族:AF_INET6
    u_inet16_t sin6_port;// 端口号:用网络字节序表示
    u_int32_t sin6_flowinfo;// 流信息,应设置为 0
    struct in6_addr sin6_addr;// IPV6 地址结构体
    u_int32_t sin6_scope_id;// scope ID,尚处于试验阶段
};
二、IP地址转换函数
通常,人们习惯用点分十进制字符串表示 IPV4 地址,但编程中我们需要先把它们转化为整数方能使用,下面函数可用于点分十进制字符串表示的IPV4 地址和网络字节序整数表示的 IPV4 地址之间的转换

#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);//字符串表示的 IPV4 地址转化为网络字节序
char* inet_ntoa(struct in_addr in);// IPV4 地址的网络字节序转化为字符串表示
三、网络编程接口
头文件:

#include <sys/types.h>
#include <sys/socket.h>

3.1 socket()
socket()创建套接字,成功返回套接字的文件描述符,失败返回-1

int socket(int domain, int type, int protocol);
domain:设置套接字的协议族,AF_UNIX 、AF_INET、 AF_INET6
type:设置套接字的服务类型 SOCK_STREAM(流式服务)、SOCK_DGRAM(数据报服务)
protocol:一般设置为 0,表示使用默认协议
 
3.2 bind()
bind()将 sockfd 与一个 socket 地址绑定,成功返回 0,失败返回-1

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd 是网络套接字描述符,(命名套接字,就是上面的函数的返回值作为了我们的参数sockfd)
addr 是地址结构
addrlen 是 socket 地址的长度
3.3 listen()
listen()创建一个监听队列以存储待处理的客户连接,成功返回 0,失败返回-1

int listen(int sockfd,int backlog);
sockfd 是被监听的 socket 套接字
back1og 表示处于完全连接状态的 socket 的上限
3.4 accept()
accept()从 listen 监听队列中接收一个连接,成功返回一个新的连接 socket,该 socket 唯一地标识了被接收的这个连接,失败返回-1

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd 是执行过 listen 系统调用的监听 socket
addr 参数用来获取被接受连接的远端 socket 地址
addrlen 指定该 socket 地址的长度
3.5 connect()
客户端需要通过此系统调用来主动与服务器建立连接,成功返回 0,失败返回-1

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
sockfd 参数是由 socket()返回的一个 socket
serv_addr 是服务器监听的 socket 地址
addrlen 则指定这个地址的长度
3.6 close()
关闭一个连接,实际上就是关闭该连接对应的socket

int close(int sockfd);
3.7 recv()、send()
TCP 数据读写:

ssize_t recv(int sockfd, void *buff, size_t len, int flags);
 
ssize_t send(int sockfd, const void *buff, size_t len, int flags);
recv()读取 sockfd 上的数据,buff 和 len 参数分别指定读缓冲区的位置和大小
send()往 socket 上写入数据, buff 和 len 参数分别指定写缓冲区的位置和数据长度
flags 参数为数据收发提供了额外的控制
3.8 recvfrom()、sento()
UDP 数据读写:

recvfrom()读取 sockfd 上的数据, buff 和 len 参数分别指定读缓冲区的位置和大小

ssize_t recvfrom(int sockfd, void *buff, size_t len, int flags.struct sockaddr* src_addr,socklen_t* addrlen);
src_addr 记录发送端的 socket 地址
addrlen 指定该地址的长度
sendto()往 socket 上写入数据, buff 和 len 参数分别指定写缓冲区的位置和数据长度

ssize_t sendto(int sockfd, void *buff, size_t len, int flags,struct sockaddr* dest_addr,socklen_t addrlen);
dest_addr 指定接收数据端的 socket 地址
addrlen 指定该地址的长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值