基本的socket函数

1.地址结构

1.1 IPv4地址结构

struct in_addr{
	in_addr_t	s_addr;
};

struct sockaddr_in
{
	uint8_t			sin_len;
	sa_family_t		sin_family;	/* 协议族 AF_INET/AF_INET6/AF_LOCAL/AF_ROUTE/AF_KEY */
	in_port_t		sin_port;	/* 端口号,网络序 */
	struct in_addr	        sin_addr;	/* 地址,网络序 */
	char			sin_zero[8];
};


 由于一些历史原因,很多函数使用通用的套接字地址结构作为参数: 

struct sockaddr
{
	uint8_t		sa_len;
	sa_family_t	sa_family;
	char		da_data;
};


1.2 IPv6地址结构

struct in6_addr{
	uint8_t	s6_addr[16];
};

struct sockaddr_in
{
	uint8_t			sin6_len;
	sa_family_t		sin6_family;	/* 协议族 AF_INET/AF_INET6/AF_LOCAL/AF_ROUTE/AF_KEY */
	in_port_t		sin6_port;	/* 端口号,网络序 */
	struct in6_addr	sin6_addr;	/* 地址,网络序 */
	uint32_t		sin6_scope_id;
};

2. 地址转换函数

2.1 字符串地址格式转换为网络序的二进制值

仅适用于IPv4;

2.1.1 inet_aton

int inet_aton(const char*strptr, struct in_addr *addrptr);

入参:

1. strptr,指向字符串的指针;

2. addrptr, 指向存储转换后数据的指针;

返回值:

字符串有效返回1,无效返回0;

2.1.2 inet_addr

in_addr_t inet_addr(const char*strptr);

入参:

1. strptr,指向字符串的指针;

返回值:

转换后数据 or INADDR_NONE;

INADDR_NONE一般为0xffffffff,所以“255.255.255.255”不能由这个函数处理;

2.2 网络序的二进制值转换为字符串地址格式

仅适用于IPv4;
char *inet_ntoa(struct in_addr inaddr);
入参: struct in_addr 而不是指针;

返回值:存储转换后结果的指针;

这个指针是静态变量,因此这个函数是不可重入的;


2.3 inet_pton和inet_ntop

这两个函数适用于IPv4和IPv6;

presentation-->numeric

int inet_pton(int family, const char *strptr, void *addrptr);

numeric-->presentation

const char* inet_ntop(int family, void *addrptr, const char *strptr, int len);


strptr为字符串地址格式;

addrptr为数值格式;

3. socket相关基本函数

3.1 socket()

#include<sys/socket.h>
int socket(int family, int type, int protocol);
入参说明:


family

说明

AF_INET

IPv4协议

AF_INET6

IPv6协议

AF_LOCAL

Unix协议域

AF_ROUTE

路由套接字

AF_KEY

秘钥套接字



type

说明

SOCK_STREAM

字节流套接字

SOCK_DGRAM

数据报套接字

SOCK_SEQPACKET

有序分组套接字

SOCK_RAW

原始套接字

protocol

说明

IPPROTO_TCP

TCP传输协议

IPPROTO_UDP

UDP传输协议

IPPROTO_SCTP

SCTP传输协议


socket在调用成功时会返回套接字描述符,失败是返回INVALID_SOCKET(-1);

一般设置参数时,将protocol设置为0,以选择给定family和type组合的系统默认值;并非每种family和type的组合都是有效的;


3.3 bind()

#include<sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
bind函数把一个本地协议地址绑定到套接字上;

用户可以指定ip地址和端口号中的任意0个、1个或两个;

如果指定端口号为0,那么内核就在bing被调用时选择一个临时端口;

如果指定的IP地址为通配地址(INADDR_ANY,一般为0),那么内核等到套接字已连接(TCP)或已在套接字上发出数据报(UDP)时才选择一个本地IP地址;

3.4 connect()

#include<sys/socket.h>
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
addr中必须含有服务器的IP地址和端口号;

对于TCP而言,connect会触发三次握手,且只在连接建立成功或失败后才返回;

如果connect失败则该套接字不再可用(此时socket的状态是未知的),必须关闭,我们不能对这样的套接字再次调用connect函数;

3.5 listen()

#include<sys/socket.h>

int listen(int sockfd, int backlog);

listen将一个未连接的套接字转换成一个被动套接字,调用socket()创建套接字时,套接字都被设置为主动套接字;

backlog指定了未完成链接队列(SYN_RECV状态)和已完成队列(ESTABLISHED状态)的最大连接个数;

不要把backlog设置为0,因为不同的实现对此的解释不同;

在三次握手完成之后,但在服务器调用accept之前到达的数据应由服务器TCP排队,最大数据量为相应已连接套接字的接收缓冲区大小;


3.6 accept()

#include<sys/socket.h>
int accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);
addrlen是值-结果型参数;

cliadd和addrlen也可以全部置为NULL,表示对客户端协议地址不关系;

accept()从已连接队列头返回一个已完成连接, 如果已完成连接队列是空的,那么进程就会进入睡眠(套接字为阻塞方式),直到TCP在该队列放入一个连接;

3.7 getsockname()和getpeername()

#include<sys/socket.h>
int getsockname(int sockfd, struct sockaddr* localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr* peeraddr, socklen_t *addrlen);
返回与sockfd关联的本地协议地址或远端协议地址;

3.8 shutdown()

#include<sys/socket.h>
int shutdown(int sockfd, int howto);

成功则返回0,出错则返回-1;

howto的取值:

①SHUT_RD,关闭连接的读这一半,套接字不再接收任何数据,并且接收缓冲区中的现有数据都被丢弃;

TCP套接字调用shutdown后,由该套接字接收的来自对端的任何数据都会被确认,然后丢弃;

②SHUT_WR,关闭连接的写这一半,当前留在发送缓冲区中的数据将被发送出去,后跟TCP的正常终止序列;

③SHUT_RDWR,读写同时关闭;









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值