Socket编程基础
运输层协议概述
TCP
:传输控制协议面向连接,可靠的数据传输协议。
UDP
:用户数据报协议无连接,不可靠的数据传输协议。
Socket
进程寻址
- socket是进程和运输层之间的接口,进程要发送网络数据,必须经由socket,交给运输层去交付。
- Socket扮演的是
邮差
的角色
TCP头部格式
-
端口是运输层的设备,网络层IP无法决定数据传输的具体位置,因此需要传输层的端口。
-
三次握手
:建立连接时候,发送方发送连接请求,接收方回复ACK同意连接,然后发送方再次确认连接。 -
四次挥手
:断开连接时,发送方发送FIN请求,接收方回复ACK同意断连,接收方再发送FIN给发送方,发送方回复ACK。
UDP头部格式
socket()创建套接字
- 函数原型
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
-
参数
domain
: AF_INET(ipv4), AF_INET6(ipv6), AF_LOCAL(本地域), AF_ROUTE(路由域)type
: SOCK_STREAM, SOCK_DGRAM, SOCK_PACKET, SOCK_SEQPACKETprotocol
: IPPROTO_TCP, IPPROTO_UDP, IPPROTO_TIPC; (一般为0,因为由前面的参数就能决定这个参数,因此默认为0即可) -
返回值
成功则返回新的文件描述符,失败则返回-1.
socket相关的结构体
bind()绑定IP和端口
-
作用
绑定自己的IP和端口
-
函数原型
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socketlen_t addrlen);
-
参数
sockfd
: 调用socket返回的文件描述符addr
: 指向数据结构struct sockaddr的指针,保存你的地址(即端口和IP地址)信息addrlen
: 设置为sizeof(struct sockaddr) -
返回值
-1出错, 0没出错
主机字节序&网络字节序
-
主机字节序(大端和小端)
小端模式:低位字节排放在内存的低地址端, 高位字节排放在内存的高地址端
大端模式:高位字节排放在内存的低地址端, 低位字节排放在内存的高地址端
-
网络字节序
4个字节的32 bit值以下面的次序传输: 首先是0-7 bit, 最后是24-31 bit
-
网络编程要把主机字节序转换为统一的网络字节序
listen()监听socket
-
函数原型
#include <sys/types.h> #include <sys/socket.h> int listen(int sockfd, int backlog);
-
参数
sockfd
: 调用socket()返回的套接字文件描述符backlog
: 是在进入队列是允许连接数目 -
返回值
错误-1,否则0
-
作用:将“邮差”由主动变为被动的接受信息
accept()接受连接
-
函数原型
#include <sys/types.h> #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-
参数
sockfd
: 必须是经由socket(), bind(), listen()函数处理后的socket*addr
: 一个地址,将保存对端地址到该地址中*addrlen
: 地址长度的地址 -
返回值
成功则返回新的sockfd, 原先的sockfd依然可以用来accept(类似于游戏中的NPC,一个用户接受用户后,其他的用户依然可以继续访问NPC)
失败则返回-1.
connect()建立连接
-
函数原型
#include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-
参数
sockfd
: 系统调用socket()返回的套接字文件描述符addr
: 是保存着目的地端口和IP地址的数据结构struct sockaddraddrlen
: 设置为sizeof(struct sockaddr) -
返回值
错误-1,成功0
-
作用
connect与accept是一对,分别在客户端和服务端执行,在此期间,完成三次握手操作。
send()发送数据
-
函数原型
#include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
-
参数
sockfd
: 想发送数据的套接字描述符msg
: 是指向你想发送的数据的指针len
: 数据的长度flags
: 设置为0即可sendto
: 主要用在UDP通信中dest_addr
: 远端要通信的网络地址addrlen
: 地址的长度 -
返回值
成功则返回成功发送的字节数
失败则返回-1, 并设置errno
recv接受函数
-
函数原型
#include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
-
参数
sockfd
: 要读的套接字描述符buf
: 要读的信息的缓冲len
: 缓冲的最大长度flags
: 可以设置为0 -
返回值
实际读入缓冲的数据字节数。出错时返回-1, 同时设置errno
close()关闭连接
-
函数原型
#include <unistd.h> int close(int fd);