APUE笔记 网络IPC

套接字描述符


#include <sys/scoket.h>

int socket(int domain, int type, int protocol);

domain 

协议族:

AF_INETipv4

AF_INET6ipv6

AF_UNIX unix域


type

套接字类型

SOCKET_STREAM 流式字节流,tcp时使用这个 

SOCKET_DGRAM   固定长度,无连接,不可靠协议  UDP使用这个

SOCKET_SEQPACKET 长度固定,有序可靠,面向连接的报文 ,读发的字节数是相等的

SOCKET_RAW  允许直接操作IP,需要root权限


type == 0 时使用默认协议 tcp udp,,,


#include <sys/socket.h>

int shutdouwn(int fd, int how);

SHUTDOWN_RD         关闭读

SHUTDOWN_WR        关闭写

SHUTDOWN_RDWR  关闭读写

相对于close 只有所有引用socket描述符(dup dup2)的都关闭才能关闭文件

shutdown 可以控制socket与 描述符引用无关!

方便控制写,读


字节序

由于历史原因,tcp/ip的字节序是打算字节序

现在很多服务器,pc都是小端序,so为支持tcp/ip,地址端口必须转换为网络地址序(大端序)

对于数据,只要发送端和接收端都是小端序就没问题!

#include <arpa/inet.h>

uint32_t htonl(uni32_t hostint32);//ip用这个

uint16_t htons(uni16_t hostint16);//端口用这个

uint32_t ntohl(uni32_t net32);//网络序转换成小端序 ip

uint16_t ntohl(uni32_t net16);//网络序转换成小端序 端口用


地址格式

struct sockaddr

{

    sa_family_t sa_family;

    char sa_data[];

...

};


struct in_addr

{

    in_addr s_addr;//ipv4的地址

};


struct sockaddr_in

{

    sa_family_t sin_family;//地址族

    in_port_t sin_port;

    struct in_addr sin_addr;//ip地址

};

family ipv4 AF_INET

          ipv6 AF_INET6


由于历史原因,在bind和connect中地址都强制转换成sockaddr


#include <arpa/inet.h>

const char* inet_ntop(int domain, const void*restrict addr, const char *restrict str, socklen_t bufsize);

socksize  str缓冲区大小,防止越界

成功返回转换后的字符串,失败返回NULL


int inet_pton(int domain, const char* restrict str, void *restrict addr);

成功返回0,失败返回-1

转换后的结果存放在add指向的地址r中


套接字绑定地址

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t len);

len 表示addr的字节长度

地址端口号必须>=1024,在root权限下可以 < 1024

必须绑定本机的地址

INADDR_ANY可以绑定到本机安装的所有网卡


可以通过getsockname 获取fd上绑定的地址,若fd未绑定地址则结果未定义

#include <sys/socket.h>

int getsocketname(int fd, struct sockaddr *restrict addr, socklen_t *alenp);

alenp填充返回的addr的字节数

地址通过addr返回

如果addr缓冲区大小不匹配,自动截断,不报错

int getpeername(int fd, struct sockaddr *restrict addr, socklen_t *alenp);

返回链接另一端的地址信息

O_NOBLOCK

int connect(int sockfd, struct sockaddr *addr, socklen_t len);

客户端可以向指定的服务器地址尝试建立连接

若服务器端,未运行可接受连接,则返回-1

对udp也可以用此函数,则此函数会将fd与目的端地址绑定

在linux下如果连接失败,还可以继续使用fd再次连接,但在有些系统中,不能再用需要用socket函数产生一个新的fd

若果是为了可移植性,需要在失败后在socket()


int listen(int fd, int backlog);

在服务器端用此函数

此函数backlog设置fd,在三次握手未成功,和刚建立连接的队列的最大排队值 tcp默认128



int accept(int fd, struct socketaddr *restrict addr, socklen_t len);

用于TCP

监听连接connect请求,客户端的地址填充到addr中,len表示addr的字节数

在fd未设置O_NOBLOCK时,阻塞直到连接请求到来

若fd设置了O_NOBLOCK,则返回-1,errno EWOULDBLOCK

成功返回一个新的 socket fd连接到客户端


tcp中有  用于accept的fd 绑定到本机的ip,用于接受连接请求

还有直接连接客户端的fd,读写的数据都是发送到客户端,读客户端的数据

accept的fd accept成功 返回连接到客户端的fd

TCP socket的服务器端& 客户端代码顺序

服务端

int fd = socket()产生一个socketfd

设置地址信息sockaddr_in ip 端口

bind(fd, &addr, len)绑定fd与本地地址

listen 设置可正在握手,和刚握手成功的等待队列大小

rwfd = accept

读写 fd


客户端

int fd = socket()产生一个socketfd

设置地址信息sockaddr_in ip 端口

connect

用fd读写

套接字选项

套接字机制使用了set 和get函数,来获取和设置socket的

通用套接字选项

套接字层次管理的选项

特定协议选项


int setsockopt(int fd, int level, int op, const void *val, sock_len len);

int getsockopt(int fd, int level, int op, void * val, socklen_t lenp);








































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章