大端:(高低低高)高位字节存储在内存地址的低地址处,低位存储在内存地址的高地址处.
小端:(高高低低)高位字节存储在内存的高地址处,低位存储在内存地址的低地址处。
即使是同一台机器上的两个进程(比如一个由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的地址。
#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;
}
#include<unistd.h>
int pipe(int fd[2]);
作用:创建双向管道.
#include<sys/types.h>
#include<sys/socket.h>
int socketpair(int domain,int type,int protocol,int fd[2]);
domain 是AF_UNIX;
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函数在两个文件描述符之间传输文件完全在内核中进行,避免了用户缓冲区和内核缓冲区之间的数据拷贝,效率大大提高.
#include<sys/sendfile.h>
ssize_t sendfile(int out_fd,int in_fd,off_t* offset,size_t count);
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);
#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);
tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作,它不消耗数据,源文件描述符上的数据仍然可以用于后续的读操作.
#include<fcntl.h>
ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);
fd_in和fd_out都必须是管道文件描述符.
对文件描述符的各种控制操作.
#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; //返回文件描述符旧的状态标志.
}