TCP套接字编程的函数---Unix网络编程笔记

start:

#include <sys/socket.h>

int socket(int family,int type,int protocol);

family:协议类型
type:套接字类型
protocol

family说明
AF_INETIPv4
AF_INET6IPv6
AF_LOCALUnix域套接字
AF_ROUTE路由套接字
AF_KEY密钥套接字
type说明
SOCK_STREAM字节流套接字
SOCK_DGRAM数据报套接字
SOCK_SEQPACKET有序分组套接字
SOCK_RAM原始套接字
protocol说明
IPPROTO_TCPTCP传输协议
IPPROTO_UDPUDP传输协议
IPPROTO_SCTPSCTP传输协议

并非所有的family和type组合都是有效的:

type\familyAF_INETAF_INET6AF_LOCALAF_ROUTEAF_KEY
SOCK_STREAMTCP,SCTPTCP,SCTP
SOCK_DGRAMUDPUDP
SOCK_SEQPACKETSCTPSCTP
SOCK_RAWIPv4IPv6

int connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen);

作用:建立与TCP服务器的连接

sockfd:socket()函数返回的套接字描述符
servaddr:指向要连接的服务器 的 套接字地址结构 的 指针
addrlen:套接字地址结构的大小,sizeof(struct sockaddr)

connect激发三次握手过程。

通常情况下,我们定义sockaddr_in数据类型进行赋值操作,函数引用的时候,使用强制类型,转换为sockaddr数据类型。

套接字地址结构(常用):

IPv4套接字地址结构:
struct sockaddr_in{ //16 bytes
	uint8_t sin_len; //1 byte
	sa_family_t sin_family; //1 byte
	in_port_t sin_port; //2 bytes
	struct in_addr sin_addr; //4 bytes
	char sin_zero[8];	 //unused 8 bytes
}
struct in_addr{ //为什么一个元素还用结构体包裹?
	in_addr_t s_addr;
}
通用套接字地址结构
struct sockaddr{ //16bytes
	uint8_t sa_len; //1 byte
	sa_family_t sa_family; 1 byte
	char sa_data[14]; //14 bytes
}

定义报文结构体时,方便定义的一些数据类型:

数据类型说明头文件
int8_t / uint8_t有/无 符号的8位整数<sys/types.h>
int16_t / uint16_t有/无 符号的16位整数<sys/types.h>
int32_t / uint32_t有/无 符号的32位整数<sys/types.h>
sa_family_t套接字地址结构的地址族<sys/socket.h>
socklen_t套接字地址结构的长度,一般uint32_t<sys/socket.h>
in_addr_tIPv4地址,一般uint32_t<netinet/in.h>
in_port_tTCP,UDP端口,一般uint16_t<netinet/in.h>

int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);

把一个本地协议地址赋给一个套接字。
bind可以指定IP地址或端口、可以两者都指定,也可以都不指定:

IP地址端口结果
通配地址0内核选择IP地址和端口
通配地址非0内核选择IP地址,进程指定端口
本地IP地址0进程指定IP地址,内核选择端口
本地IP地址非0进程指定IP地址和端口

通配地址,常由INADDR_ANY指定,值一般为0。

int listen(int sockfd, int backlog);

listen()函数把一个未连接的套接字转换成一个被动套接字,指示内核应接受指向该套接字的连接请求。
backlog规定了内核应该为相应套接字排队的最大连接个数。

内核为任何一个给定的监听套接字维护两个队列:
未完成连接队列:收到客户SYN分节,但尚未完成三次握手
已完成连接队列:完成三次握手
两个队列之和不大于backlog。

进程调用accept()时,已完成连接队列中的队头项返回给进程,如果该队列为空,进程就等到队列里面被放进来一项为止。

int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen);

sockfd:监听套接字。
参数cliaddr 和 addrlen用来返回已连接的对端进程的协议地址。

如果accept成功,返回值是由内核自动生成的一个全新的描述符,代表服务器和客户端之间的TCP连接,也被成为已连接套接字

int close(int sockfd);

#include <unistd.h>
close一个TCP套接字的默认行为是把该套接字标记成已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用。

并发服务器中父进程关闭已连接套接字只是导致相应描述符的引用计数减一,除非刚好减一为零,否则close调用并不能引发TCP四分组连接终止序列。这是并发服务器所希望的。

若确实希望直接进行“四次挥手”,可以将close改为shutdown函数。

int getsockname(int sockfd,struct sockaddr *localaddr,socklen_t *addrlen);

得到与某个套接字关联的本地协议地址

int getpeername(int sockfd,struct sockaddr *peeraddr,socklen_t *addrlen);

得到与某个套接字关联的外地协议地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值