文章目录
一、接口说明
1、socket 函数
功能:创建网络套接字
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
/*
domain: 协议族(某种意义上看,它指定了网络层协议)
Name Purpose Man page
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK AppleTalk ddp(7)
AF_PACKET Low level packet interface packet(7)
AF_ALG Interface to kernel crypto API
type:(概念上将,这字段靠向传输层协议)
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-
of-band data transmission mechanism may be supported.
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum
length).
SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-based data transmission path
for datagrams of fixed maximum length; a consumer is required to read an entire
packet with each input system call.
SOCK_RAW Provides raw network protocol access.
SOCK_RDM Provides a reliable datagram layer that does not guarantee ordering.
SOCK_PACKET Obsolete and should not be used in new programs; see packet(7).
protocol:(具体协议,比如TCP/IP)
具体协议,一般来说,domain和type指定完毕,protocol应该默认被推测出来;
但是如果满足的协议有多个,需要用户指出需要的协议是哪一个
*/
2、端到端或者点到点
2.1 字节序转换
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
2.2 地址类型
-
不同操作系统,不同通信协议其地址数据格式是不同的:为了体现点到点或者端到端通信,IP网络协议都有ip字段,传输层协议有端口字段
POSIX.1-2001, POSIX.1-2008 /*af:AF_INET或者AF_INET6,分别表示ipv4.,ipv6*/ /* 组合1: (AF_INET,"192.168.1.101",struct in_addr*) 组合2: (AF_INET6,"255.255.255.255.255.90",struct in6_addr*) */ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); int inet_pton(int af, const char *src, void *dst);
2.3、套接字与地址绑定
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
示例代码:
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MY_SOCK_PATH "/somepath"
#define LISTEN_BACKLOG 50
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int sfd, cfd;
struct sockaddr_un my_addr, peer_addr;
socklen_t peer_addr_size;
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
handle_error("socket");
memset(&my_addr, 0, sizeof(struct sockaddr_un));
/* Clear structure */
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, MY_SOCK_PATH,
sizeof(my_addr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("bind");
if (listen(sfd, LISTEN_BACKLOG) == -1)
handle_error("listen");
/* Now we can accept incoming connections one
at a time using accept(2) */
peer_addr_size = sizeof(struct sockaddr_un);
cfd = accept(sfd, (struct sockaddr *) &peer_addr,
&peer_addr_size);
if (cfd == -1)
handle_error("accept");
/* Code to deal with incoming connection(s)... */
/* When no longer required, the socket pathname, MY_SOCK_PATH
should be deleted using unlink(2) or remove(3) */
}
2.4、客户网络端口请求建立连接
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
!!!需要注意的是,因为服务器可能十分繁忙;用户建立连接的请求可能会失败(客户程序需要处理这种情况)
又及:
connect常见于面向连接的应用,但是使用SOCK_DGRAM这种非面向连接的模式也是不错的选择。这样以后发送报文的默认地址会成为connect连接指定的地址
2.5、服务器网络端口接收连接请求
-
首先,服务器调用listen函数
listen设置socket为被动接收连接请求模式,同时指定了可接受的连接上限(当连接超过backlog之后,客户端连接失败)#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int listen(int sockfd, int backlog);
-
然后,服务器调用accept函数等待用户连接请求
accept返回一个connet fd,表示一个建立的链接…connect fd与sockfd有着相同类型的protocol,但是彼此并不关联
(getsockname getpeername可以获取本端或者对端的网络地址)#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
3、数据传输
通过connect fd用户有多种选择实现发送数据或者接收数据
3.1 write/read
功能简单,但易用,同时具备较好的兼容性
3.2 send/sendto/sendmsg/recv/recvfrom/recvmsg
发送接口
#include <sys/types.h>
#include <sys/socket.h>
/*socket处于链接状态*/
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
/*socket 处于非链接状态*/
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
/*用于发送多重缓冲数据,类似writev*/
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
send与write区别在于flags参数
接收接口
#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);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
flags
recvmsg返回flag状态
4、实例
4.1
4.2
4.3
5、其它
5.1 配置套接字
用户可以配置传输层,网络层等协议栈的特性
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);