socket 地址常用的API总结

主机字节序和网络字节序

大端:(高低低高)高位字节存储在内存地址的低地址处,低位存储在内存地址的高地址处.

小端:(高高低低)高位字节存储在内存的高地址处,低位存储在内存地址的低地址处。
即使是同一台机器上的两个进程(比如一个由c语言编写,另一个由java编写)通信,也要考虑字节序的问题(java 虚拟机采用大端字节序);
accept只是从监听队列中取出连接,而不论连接处于何种变化,更不关心任何网络状况的变化.

#include<unistd.h>
int close(int fd);

fd是待关闭的socket,不过,close系统调用并非总是立即关闭一个连接,而是将fd的引用计数减1,只有当fd的引用计数为0时,才真正关闭连接,在多进程程序中,一次fork系统调用默认将使父进程中打开的socket的引用计数加1,因此我们必须在父进程和子进程中都对该socket执行close调用才能将连接关闭.

立即终止连接

#include<sys/socket.h>
int shutdown(int sockfd,int howto); 

howto选项的值:
SHUT_RD:关闭sockfd上读的这一半,应用程序不能再针对socket文件描述符执行读操作,并且该socket接收缓冲区中的数据都将被丢弃.
SHUT_WR:关闭sockfd上写的这一半,sockfd的发送缓冲区中的数据会在真正关闭连接之前全部发出去,应用程序不可对该socket文件描述符执行写操作,这种情况下,连接处于半关闭状态。
SHUT_RDWR:同时关闭sockfd上的读和写。

#include <sys/socket.h>
int sockatmark(int sockfd);

sockatmark判断sockfd是否处于带外标记,即下一个被读取到的数据是否是带外数>>据,如果是,sockmark返回1,此时我们就可以利用带MSG_OOB标志的recv调用来接>>收带外数据,如果是不是,则返回0.

#include<sys/socket.h> 
int getscokname(int sockfd,struct sockaddr * address,socklen_t* address_in); 
int getpeername(int sockfd,struct sockaddr * address,socklen_t * address_in); 

getsockname获取sockfd对应的本端的socket地址,并将其存储于address参数指定的内存,getpeername获取对应的远端的socket的地址。

网络信息 API

#incldue<netdb.h>
struct hostent *gethostbyname(const char* name);
struct hostent *gethostbyaddr(const void * addr,size_t len,int type);
struct hostent
{
    char * h_name;
    char** h_aliases;  //主机别名;
    int h_addrtype;   //地址类型
    int  h_length;  //地址长度
    char **h_addr_list;   //按网络字节序列列出主机IP地址列表
}
name:目标主机的主机名.
addr:指定目标主机的IP地址,len参数指定addr所指的IP地址的长度,type参数指定addr所指IP的类型,AF_INET或AF_INET6;   
#include<netdb.h>
struct servent* getservbyname(const char* name,const char* proto);
struct servent* getservbuport(int port,const char *proto);
name:目标服务的名字;
port:端口 
proto:指定服务类型
eg:'tcp'or'udp';
struct servent 
{
    char * s_name;  
    char ** s_aliases;
    int s_port;
    char* s_proto;  //服务类型,通常是TCP或者UDP;
}

pipe 函数

#include<unistd.h>
int pipe(int fd[2]);
  • fd[2]是一个包含两个int型整数的数组的指针,该函数成功将一对打开的文件描述符填入其参数指向的数组.
  • fd[0]只能用于从管道中读出数据.fd[1]只能用于往管道中写数据.
  • 默认情况下,这两个文件描述符是阻塞的.
  • 用read读一个 没有数据的管道,read会被阻塞,直到管道中有数据.
  • 用write向一个满的管道写数据,则write会阻塞,直到管道有足够多的空间可用.

socketpair函数

作用:创建双向管道.

#include<sys/types.h>
#include<sys/socket.h>
int socketpair(int domain,int type,int protocol,int fd[2]);
domain 是AF_UNIX;

dup 和dup2函数

  • dup函数创建一个新的文件描述符,该文件描述符和原有的文件描述符file_descriptor指向相同的文件,管道或者网络连接,返回当前系统最小的可用的整数值.
  • dup2 它返回第一个不小于file_descriptor_two的整数值.
  • dup和dup2创建的文件描述符并不继承原文件描述符放入属性,比如close-on-exec等;

readv函数和writev函数

readv函数将数据从文件描述符读到分散的内存中,writev函数将多块分散的内存数据一并写入文件描述符.

#include<sys/uio.h>
ssize_t readv(int fd,const struct iovec * vector,int count);
ssize_t writev(int fd,const struct iovec * vector,int count);
struct iovec
{
    void * iov_base;   //内存的起始块
    size_t iov_len;  //内存的长度; 
}

fd参数是被操作的目标文件描述符,vector参数iovec结构体数组count参数是vector数组的长度,即有多少块内存数据需要从fd读出或写到fd.成功返回写入或读出fd的字节数.

sendfile函数

sendfile函数在两个文件描述符之间传输文件完全在内核中进行,避免了用户缓冲区和内核缓冲区之间的数据拷贝,效率大大提高.

#include<sys/sendfile.h>
ssize_t sendfile(int out_fd,int  in_fd,off_t* offset,size_t count);
  • in_fd参数是待读出内容的文件描述符.
  • out_fd参数是待写入数据的文件描述符.
  • offset 参数指定从读入文件流的哪个位置开始读,如果为空,默认从起始位置。
  • count 参数指定在文件描述符之间传输的字节数.
  • in_fd必须是类似于mmap函数的文件描述符,必须指向真实的文件,不能是socket或管道,out_fd必须是socket.

mmap函数和munmap函数

mmap函数用于申请一段内存空间,我们可以将这块内存空间作为进程间通信的共享内存,也可以将文件直接映射到内存中,munmap函数释放mmap创建的这段空间.

#include<sys/mman.h>
void *mmap(void *start,size_t length,int prot,int flags,int fd,(off_t offset));
int munmap(void *start,size_t length);
  • start用于指定起始地址,为空,则系统自动分配一个地址,
  • length指定内存段的长度,
  • prot参数用来设置内存段的访问权限.
    (1)PROT_READ:内存段可读。
    (2)PROT_WRITE:内存段可写。
    (3)PROT_EXEC:内存段可执行.
    (4)PROT_NONE:内存段不可被访问.
  • flags参数控制内存段内容被修改后程序的行为.它可以被设置
    (1)MAP_SHARED 在进程间共享这段内存,对该段内存段的修改将反应到被映射的文件中.
    (2)MAP_PRIVATE: 内存段为调用进程所私有,对该段内存段的修改不会反映到被映射的文件中.
    (3)MAP_ANONYMOUS:这段内存不是从问价映射而来的,其内容被初始化为全0,这种情况,mmap的最后两个参数被忽略.
    (4)MAP_FIXED:内存段必须位于start参数指定start参数指定的地址处,start必须是内存页面的大小(4096)的整数倍。
    (5)MAP_HUGETLB:按照”大内存页面”来分配内存空间,”大内存页面’的大小可通过/proc/meminfo 来查看。
    *fd参数是被映射文件对应的文件描述符,一般通过open系统调用来获得.

spilce 函数

#include<fcntl.h>
ssize_t spilce(int fd_in,loff_t* off_in,int fd_out,loff_t* off_out,size_t len,unsigned int flags);  
  • 用于在两个文件描述符之间移动数据,零拷贝.
  • fd_in 参数是待输入数据的文件描述符,如果fd_in是一个管道文件描述符,那么off_in参数必须被设置为NULL, off表示从输入流的何处开始读取数据,fd_out/off_out用于输出数据流,flags参数控制如何移动数据。
  • fd_in和fd_out必须至少有一个是管道文件描述符.

tee函数

tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作,它不消耗数据,源文件描述符上的数据仍然可以用于后续的读操作.

#include<fcntl.h>
ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);

fd_in和fd_out都必须是管道文件描述符.

fcntl 函数

对文件描述符的各种控制操作.

#include<fcntl.h>
int fcntl(int fd,int cmd...)

非阻塞的文件描述符的设置

int setnonblocking(int fd)
{
    int old_option=fcntl(fd,F_GETFL);  //获取文件描述符的状态。
    int new_option=old_option | O_NONBLOCK;  //设置非阻塞标志
    fcntl(fd,F_SETFL,new_option);  
    return old_option;    //返回文件描述符旧的状态标志.
}

你可能感兴趣的:(socket,api)