常用api
#include <sys/socket.h>
//成功返回非负整数,出错返回-1
SOCKET WSAAPI socket(
int af, //地址族规范。 地址族的可能值在Winsock2.h头文件中定义。
int type,//新套接字的类型规范。
int protocol//要使用的协议。
);
//最常用选项
/*
af AF_INET Internet协议版本4(IPv4)地址族。
AF_INET6 Internet协议版本6(IPv6)地址族。
type SOCK_STREAM 字节流套接字
SOCK_DGRAM 数据报套接字
SOCK_SEQPACKET 有序分组套接字
protocol IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_SCTP SCTP传输协议
*/
2.connect函数(建立与tcp服务器的连接)
#include <sys/socket.h>
//成功返回0,出错返回-1
int WSAAPI connect(
_In_ SOCKET s,
_In_reads_bytes_(namelen) const struct sockaddr FAR * name,
_In_ int namelen
);
/*
s->标识一个未连接socket
name:指向要连接套接字的sockaddr结构体的指针
namelen:sockaddr结构体的字节长度
*/
bind函数(绑定ip与端口)
#include <sys/socket.h>
//成功返回0,出错返回-1
int bind(int sockfd, const struct sockaddr, socklen_t addrlen);
/*
sockfd:由socket函数返回的fd
name:指向要连接套接字的sockaddr结构体的指针
#define INADDR_ANY (ULONG)0x00000000
由内核分配ip地址
addrlen:sockaddr结构体的字节长度
*/
listen(使套接字进入监听状态)
#include <sys/socket.h>
//成功返回0,出错返回-1
int listen(int sock, int backlog);
/*
sock:由socket函数返回的fd
backlog:请求队列的最大长度。
*/
accept()
#include <sys/socket.h>
//成功返回fd,出错返回-1
int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);
/*
sock:由socket函数返回的fd
addr:指向要连接套接字的sockaddr结构体的指针
addrlen:sockaddr结构体的字节长度
*/
revcform & sendto(UDP接收与发送api)
udp也可以调用connect,与tcp不同,udp只会使内核记录ip和port,减少性能消耗,并且可以多次调用(1.断开原本连接,2.重新建立连接)
#include <sys/socket.h>
int recvfrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, int *fromlen);
int sendto(int s, const void *buf, int len, unsigned int flags,
const struct sockaddr *to, int tolen);
//成功则返回实际接收到的字符数,失败返回-1,错误原因会存于errno 中。
/*
s: socket描述符;
buf: UDP数据报缓存区(包含所接收的数据);
len: 缓冲区长度。
flags: 调用操作方式(一般设置为0)。
from: 指向发送(接收)数据的客户端地址信息的结构体(sockaddr_in需类型转换);
fromlen:指针,指向from结构体长度值。
*/
终止网络连接的通常方法是调用close 函数。不过close 有两个限制,却可以使用shutdown 来避免。
(1) close 把描述符的引用计数减1,仅在该计数变为0时才关闭套接字。我们已在4.8节讨论过这一点。使用shutdown 可以不管引用计数就激发TCP的正常连接终止序列(图2-5中由FIN开始的4个分节)。
(2) close 终止读和写两个方向的数据传送。既然TCP连接是全双工的,有时候我们需要告知对端我们已经完成了数据发送,即使对端仍有数据要发送给我们。这就是我们在前一节中遇到的str_cli 函数在批量输入时的情况。图6-12展示了这样的情况下典型的函数调用
#include <sys/socket.h>
int shutdown(int sockfd, int howto);
/*
返回:若成功则为0,若出错则为-1
该函数的行为依赖于howto 参数的值。
SHUT_RD 关闭连接的读这一半——套接字中不再有数据可接收,而且套接字接收缓冲区中的现有数据都被丢弃。进程不能再对这样的套接字调用任何读函数。对一个TCP套接字这样调用shutdown函数后,由该套接字接收的来自对端的任何数据都被确认,然后悄然丢弃。
默认情形下,写入一个路由套接字(第18章)中的所有数据都被作为同一个主机上所有路由套接字的可能输入环回。有些程序把第二个参数指定为SHUT_RD 来调用shutdown 函数以防止环回复制。防止环回复制的另一种方法是关闭SO_USELOOPBACK 套接字选项。
SHUT_WR 关闭连接的写这一半——对于TCP套接字,这称为半关闭 (half-close,见TCPv1的18.5节)。当前留在套接字发送缓冲区中的数据将被发送掉,后跟TCP的正常连接终止序列。我们已经说过,不管套接字描述符的引用计数是否等于0,这样的写半部关闭照样执行。进程不能再对这样的套接字调用任何写函数。
SHUT_RDWR 连接的读半部和写半部都关闭——这与调用
shutdown 两次等效:第一次调用指定SHUT_RD ,第二次调用指定SHUT_WR 。
*/