#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<errno.h>
voidconstchars)
{
s);
exit(1);
}
intintfd, structsockaddrsa, socklen_tsalenptr)
{
int n;
again: //accrpt是慢速系统调用,在阻塞期间可能会被信号杀死
iffd, sa, salenptr)) < 0) {
iferrnoECONNABORTED) || (errnoEINTR))//进一步判断返回值,EINTR代表函数被信号中断;ECONNABORTED代表连接中断,这两种情况不算是异常,所以重启
goto again;
else
"accept error");
}
return n;
}
intintfd, conststructsockaddrsa, socklen_tsalen)
{
int n;
iffd, sa, salen)) < 0)
"bind error");
return n;
}
intintfd, conststructsockaddrsa, socklen_tsalen)
{
int n;
iffd, sa, salen)) < 0)
"connect error");
return n;
}
intintfd, intbacklog)
{
int n;
iffd, backlog)) < 0)
"listen error");
return n;
}
intintfamily, inttype, intprotocol)
{
int n;
iffamily, type, protocol)) < 0)
"socket error");
return n;
}
ssize_tintfd, voidptr, size_tnbytes)
{
ssize_t n;
again: //read也是慢速系统调用。
iffd, ptr, nbytes)) == -1) {
iferrnoEINTR)
goto again;
else
return -1;
}
return n;
}
ssize_tintfd, constvoidptr, size_tnbytes)
{
ssize_t n;
again:
iffd, ptr, nbytes)) == -1) {
iferrnoEINTR)
goto again;
else
return -1;
}
return n;
}
intintfd)
{
int n;
iffd)) == -1)
"close error");
return n;
}
/*
应用场景:以太网帧一次最多发送1500字节的数据,若是我们要读取4096字节的数据,但是4096字节的数据需要四次才能完全发送过来,如果只调用一次read,那就只能读到1500就返回不读了,所以我们需要让系统调用多次,必须读够那么多数据。所以这次调用,n要等于4096
//参数三:应该读取到的字节数*/
ssize_tintfd, voidvptr, size_tn)
{
size_t//unsigned int 剩余未读取的字节数
ssize_t//int 实际读取到的字节数
char *ptr;
char*)vptr;
n; //n 未读取到的字节数
while (nleft > 0) {
iffd, ptr, nleft)) < 0) {
iferrnoEINTR)// EINTR(表"被信号中断")
// 读到了0个字节
else
return//其他错误
}
elseif// 文件读取完
break;
nleft -= nread;
ptr += nread;
}
returnn//返回实际读取到的字节数
}
ssize_tintfd, constvoidvptr, size_tn)
{
size_t//剩余未写的字节数
ssize_t//实际写的字节数
constchar *ptr;
char*)vptr;
n; //未写的字节数
while (nleft > 0) {
iffd, ptr, nleft)) <= 0) {
iferrnoEINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
returnn;
}
staticssize_tconstintfd, charptr)
{
staticint read_cnt;
staticchar *read_ptr;
staticchar//读一次可以传出100字节,但是不是一次性传出100字节,实际上是一次传一个字符出去
if (read_cnt <= 0) {
again:
iffd, read_buf, sizeof(read_buf))) < 0) {
iferrnoEINTR)
goto again;
return -1;
}
elseif (read_cnt == 0)
return 0;
read_ptr = read_buf;
}
read_cnt--;
ptr = *read_ptr++;
return 1;
}
/*
应用场景:fgets只能从普通文件或者标准输入输出设备读去数据,他不能从socket中读取数据,所以用readline代替fgets来读取一行
*/
ssize_tintfd, voidvptr, size_tmaxlen)
{
ssize_t n, rc;
char c, *ptr;
char*)vptr;
formaxlen; n++) {
iffd, &c)) == 1) {
*ptr++ = c;
if'\n')
break;
}
elseif (rc == 0) {
*ptr = 0;
return n - 1;
}
else
return -1;
}
*ptr = 0;
return//返回读到的字节数
}