网络字节序和本机字节序
本机字节序:小端字节序,高位存在高地址,低位存在低地址。
本机字节序:大端字节序,高位存在低地址,低位存在高地址。
htonl:通常用来将本机IP转换为网络字节序。
htons:通常用来将本机PORT转换为网络字节序。
ntohl:通常用来将IP从网络字节序转换为本机字节序。
ntohs:通常用来将PORT从网络字节序转换为本机字节序。
IP地址转换
inet_pton:将本地字节序的string IP转化成网络字节序二进制的IP地址。
inet_ntop:将网络字节序二进制的IP地址转化成本地字节序的string IP。
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
sockaddr_in结构
struct sockaddr_in{
sa_family_t sin_family; //AF_INET、AF_INET6
in_port_t sin_port; //网络字节序端口号
struct in_addr sin_addr; //网络字节序IP地址
}
struct in_addr{
uint32_t s_addr;
}
struct sockaddr_in addr;
addr.sin_addr.addr = htonl(INADDR_ANY); //INADDR_ANY宏可取出可用的本机字节序IP
socket函数
int socket(int af, int type, int protocol);
返回一个套接字描述符,失败返回-1。
af(IP协议):AF_INET、AF_INET6、AF_UNIX。
type(数据传输协议):SOCK_STREAM、SOCK_DGRAM。
protocol(代表协议,比如SOCK_STREAM代表协议TCP,SOCK_DGRAM代表协议UDP):默认填0。
bind函数
int bind(int sockfd, const struct sockaddr, socklen_t addrlen);
bind(fd, (struct sockaddr*)&addr, sizeof(addr));
给socket绑定一个IP和PORT。成功返回0,失败返回-1。
listen函数
int listen(int sockfd, int backlog);
设置同时可与服务器建立连接的上限数,即同时进行三次握手
的客户端的数量。
accept函数
int accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen);
阻塞等待客户端建立连接,成功则返回与客户端成功建立通信的套接字描述符。
addr是建立成功的客户端地址。
addrlen是客户端地址的长度。
connect函数
int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
阻塞等待客户端与服务器建立连接,成功则返回0,失败返回-1。
addr是建立成功的客户端地址。
addrlen是客户端地址的长度。
如果客户端不适用bind绑定客户端地址结构,则采用隐式绑定,系统自动绑定。
setsockopt函数
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
int opt = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt , sizeof(opt));
设置端口复用,允许端口被重复使用。
fcntl函数
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
常用fcntl(fd, F_SETFL, fcntl(_fd, F_GETFL, 0) | O_NONBLOCK)
来设置非阻塞。
read
ssize_t read(int fd,void * buf ,size_t count);
读fd套接字描述符数据,数据将读到buf 缓冲区,最多读取count个字节的数据。
返回0代表读到文件末尾,对端套接字关闭。
返回大于0代表读到数据的字节数。
返回-1代表出错,此时errno
如果是EINTR
为异常中断需要重新读,errno
如果是EAGIN
或EWOULDBLOCK
为以非阻塞的方式读数据但是没有数据。其它情况都是发生了错误。
write
ssize_t write (int fd,const void * buf,size_t count);
向fd套接字描述符写数据,数据将从buf 缓冲区读取count个字节的数据写入fd的读缓冲区。
TCP通信流程
1.socket()创建scoket;
2.bind()绑定服务器地址结构;
3.listen()设置监听上限;
4.accept()阻塞监听客户端连接;
5.connect()客户端与服务器连接。