1. bzero和memset
bzero是传统BSD函数,属于POSIX标准,使用头文件string.h,bzero无返回值,推荐使用memset替代bzero。
bzero(&servaddr, sizeof(servaddr));
memset(&remote_addr, 0, sizeof(remote_addr));
2. perror和stderr
perror和strerror都是C语言提供的库函数,用于获取与errno相关的错误信息。
不同的是perror向stderr输出结果,strerror(errno)向stdout输出结果。
一般用法:
#include <errno.h> //errno
#include <string.h> //strerror
#include <stdio.h> //stdin, stdout, stderr, perror
fprintf(stderr, "ERROR: %s\n", strerror(errno)); //把errno转化成字符串输出到标准错误
perror("ERROR"); //输出到标准错误,会在ERROR后面自动添加: errno错误
3. hton系列和inet_ntoa
htons()作用是将端口号由主机字节序转换为网络字节序的整数值,host to net short的意思。类似的函数还有htonl针对的是32位。反函数是ntohs()和ntohl()。
inet_ntoa()作用是将一个sin_addr结构体输出成IP字符串,反函数是inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值,从而用于sockaddr_in.sin_addr.s_addr。
4. read/write和recv/send
字面上看read/write提供了对文件的IO操作,recv/send则是专用于网络IP的。而在linux中,文件、目录、网络设备、串口都可以看成是文件。所以,在网络IO中经常看到read/write函数。具体不同:
int read(int fd, char *buf, int len),返回len或者实际长度或者0(连接关闭)或者错误(连接被复位),当接收缓冲区中没有数据时read函数阻塞,也就是说>=0成功,-1失败,errno为错误代码。
int write(int fd, char *buf, int len),发送缓冲区中空间小于参数len时write函数会阻塞,返回值参考read。
int recv(int sockfd, void buf, int len, int flags)
int send(int sockfd, void buf, int len, int flags)
可以发现,recv和send多了一个参数flags,当flags=0时是和read/write一样的,此外,flags可以取:
MSG_DONTROUTE表示发送数据不查找路由表,适用于局域网或同一网段,
MSG_OOB表示发送和接收带外数据
MSG_PEEK 接收数据时不从缓冲区移走数据,其他进程调用read和recv仍然可以读到数据
MSG_WAITALL 数据量不够时,读操作等待不返回,除非有中断信号或是错误
5. open系列和fopen系列
int open(const char * path, int access, int mode);
FILE *fopen(char * filename, char * mode);
最本质的区别是,二者所处的层次不同,open是UNIX/LINUX系统调用,位于fopen底层,而fopen则是标准C库函数,可移植。再往细致点的区别有很多:
open返回的是UNIX/LINUX中的文件描述符是整数值,文件句柄是文件在文件描述符表里的索引;fopen返回的是一个FILE *指针,指向文件结构的指针。
UNIX/LINUX中任何设备都是文件,都可以用open系列函数。fopen用来操作普通文件。
open系列是非缓冲文件系统操作函数,fopen系列是针对缓冲文件系统。缓冲文件系统的特点是:在内存开辟一个缓冲区,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存缓冲区,装满后再从内存缓冲区依次读入接收的变量,减小操作外存的次数,fread fwrite fgetc fgets fputc fputs fseek等。fopen在用户态下就有了缓存,在进行read和write时减少了用户态和内核态的切换,如果顺序访问文件,fopen系列的函数要比直接调用open系列快,随机访问的话open系列比fopen系列快。
open系列是低级IO,fopen系列是高级IO,fopen系列是在open系列的基础上扩充而来。