概述
参考书:《Linux网络编程(第2版)》,宋敬彬等编著。
1.TCP通信流程
tcp连接过程
图片来源: https://blog.csdn.net/u012234115/article/details/54142273
2. 套接字基础知识
通用套接字数据结构
struct sockaddr{ //套接字地址结构
sa_family_t sa_family, //协议族,类型为usigned_short
char sa_data[14] //协议族数据
}
实际使用的套接字数据结构
struct sockaddr_in { //以太网套接字地址结构
u8 sin_len, //本结构体的长度
u8 sin_family, //协议族,通常与socket的domain相同
u16 sin_port, //16位的端口号,网络字节序
struct in_addr sin_addr, //IP地址,32位
char sin_zero[8] //未用
}
struct in_addr{ //IP地址结构
u32 s_addr //32位IP地址,网络字节序
}
sockaddr_in.sin_family一般取值AF_INET表示TCP/IP协议。
sockaddr与sockaddr_in的大小完全一致,因此通常使用sockaddr_in进行设置,然后强制转换为sockaddr。
3. 创建套接字函数 socket()
socke()函数建立一个套接字文件描述符,调用成功返回文件描述符,失败返回-1.
#include #include int socket(
int domain, //设置网络通信域,根据此参数选择协议族
int type, //设置套接字类型
int protocol //用于指定某个协议的特定类型
)
domain
名称
含义
名称
含义
PF_UNIX,PF_LOCAL
本地通信
PF_X25
ITU-T X.25/ISO-8208协议
PF_INET,AF_INET
IPv4 Internet协议
PF_AX25
amateur radio AX.25协议
PF_INET6
IPv6 Internet协议
PF_ATMPVC
原始ATM PVC访问
PF_IPX
IPX-Novell协议
PF_APPLETALK
appletalk
PF_NETLINK
内核用户界面设备
PF_PACKET
底层包访问
type
名称
含义
SOCK_STREAM
Tcp连接,支持带外数据传输
SOCK_DGRAM
支持udp连接
SOCK_SEQPACKET
序列化包
SOCK_RAW
Raw类型,提供原始网络协议访问
SOCK_RDM
提供可靠的数据报文,不过可能数据会有乱序
SOCK_PACKET
专用类型,不能在通用程序中使用
SOCK_STREAM的套接字表示双向的字节流,与管道类似,流式套接字在进行通信之前必须已经使用connect()建立连接。连接中可以使用read() 和write()进行数据传输。流式通信保证数据不会丢失或重复接受,当数据在一定时间内仍没有接受完毕,可认为这个连接已经死掉。
protocol
用于指定某个协议的特定类型,通常协议中只有一种类型,protocol取值为0.
errno
值
含义
EACCES
没有权限建立制定的domain的type的socket
EAFANOSUPPORT
不支持所给的地址类型
EINVAL
不支持此协议或者协议不可用
EMFILE
进程文件表溢出
ENFILE
已经达到系统允许打开的文件数量,打开文件过多
ENOBUFS/ENOMEM
内存不足。socket只有到资源足够或者有进程释放内存
EPROTONOSUPPORT
制定的协议type在domain中不存在
其他
4. 绑定地址端口 bind()
bind()函数将套接字和指定的端口进行绑定,如果使用connect()函数则没有绑定的必要。绑定成功返回0,失败返回-1.
#include #include int bind(
int sockfd, //文件描述符
const struct sockaddr *my_addr, //sockaddr结构体指针
socket_t addrlen //sockaddr结构体的长度
)
errno
值
含义
备注
EADDRINUSE
给定地址已用
EBADF
sockfd不合法
EINVAL
sockfd已经绑定到其他地址
ENOTSOCKET
sockfd不是socket描述符
EACCESS
地址被保护,用户权限不足
待补充
5. 监听本地端口 listen()
服务器顺序处理客户端连接,同一时间只能处理一个客户端连接。当多个客户端连接请求同时到来时,将不能处理的客户端连接请求放到等待队列中,队列长度由listen()定义。
listen()函数仅对SOCK_STREAM和SOCK_SEQPACKET的协议有效。
设置成功返回0,失败返回-1.
#include int listen(
int sockfd, //侦听的描述符
int backlog //队列最大长度
)
errno
值
含义
EADDRINUSE
另一个socket已经在同一端口侦听
EBADF
sockfd不合法
ENOTSOCK
sockfd不是socket的描述符
EOPNOTSUPP
socket不支持listen操作
6. 接收一个网络请求 accept()
当一个客户端的请求到达服务器时,会在队列中等待,直到服务器处理请求。
accept()函数执行成功,返回表示客户端连接的socket描述符,失败返回-1.
#include #include int accept(
int sockfd, //监听的文件描述符
struct sockaddr *addr, // 存储客户端信息的结构体
socket_len *addrlen //上结构体的长度
)
accept()函数调用成功后,会将客户端的信息存储在*addr指向的结构体中。
errno
值
含义
待补充
7. 连接目标服务器 connect()
客户端建立套接字之后,不需要进行绑定就可以使用connect()函数直接连接服务器。connect()成功返回0,失败返回-1.
#include #include int connect(
int sockfd, //需要与服务器连接的文件描述符
struct sockaddr *addr, //包含服务器信息的结构体
int addrlen // 上述结构体的长度
)
errno
值
含义
待补充
8. 写入函数 write() & send()
使用write()对套接字写入的方式与对普通文件的操作一样。
ssize_t write(
int fd, //文件描述符
const void *buf, //数据缓存区
size_t nbytes//写入字符的大小
);
返回值大于0:返回写入数据的大小,并不一定写入了指定的全部数据,所以一般放在while循环里。
返回值小于0:EINTR表示在写的时候出现了中断错误。EPIPE表示网络连接出现问题。
send()函数功能与write()类似,提供了第四个函数控制发送操作。
int send(
int sockfd,//文件描述符
void *buf,//数据缓存区
int len,//数据大小
int flags
);
flags值
含义
MSG_DONTROUTE
send函数使用的标志,表示目的主机在本地网络上,不需要查找表
MSG_OOB
可以接受和发送带外的数据
9. 读取函数 read() & recv()
read()从套接字中读取数据。
ssize_t read(
int fd,//文件描述符
void *buf,//数据缓存区
int length//要读的数据大小
);
返回值等于0:已经读到文件结尾。
返回值大于0:实际读的数据大小。
返回值小于0:与write相同。
recv()功能与read()类似,添加了第四个参数控制接受操作。
int recv(
int sockfd,//文件描述符
void *buf,//数据缓存区
int len,//数据大小
int flags
);
flags值
含义
MSG_OOB
可以接受和发送带外的数据
MSG_PEEK
recv使用的标志,只从缓冲区读取数据而清除其内容,下次读时仍然是一样的内容,一般用在多进程读写数据时
MSG_WAITALL
recv使用的标志,表示等到所有信息都到达时才返回。当1.读到指定数据大小,返回len2.读到文件结尾返回值小于等于len3.操作发生错误时返回-1
10. 关闭套接字 close() & shutdown()
关闭连接可以用close()实现,关闭之后就不再使用此描述符进行数据收发。
#include int close( int sockfd)
shutdown()函数可以使用更多方式关闭连接,调用成功返回0,失败返回-1。
#include int shutdown(
int sockfd, // 要关闭的描述符
int how //关闭方式
)
how
值
含义
SHUT_RD
0,切断读,不能通过此方式进行读操作
SHUT_WR
1,切断写,不能通过此方式进行写操作
SHUT_RDWR
2,切断读写,与close相同
最后
以上就是舒适香氛为你收集整理的linux tcp的结构体编程,Linux编程:TCP编程基础的全部内容,希望文章能够帮你解决linux tcp的结构体编程,Linux编程:TCP编程基础所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复