Socket编程
[toc]
C/S模式
(Client) (Server)
socket() socket()
| bind()
|->sendto()------------------->recvfrom()<--|
|--rrecvfrom()<----------------sendto()-----|
close()
应用
实时音视频传输
DNS的域名解析包
头:
#include <sys/types.h>
#include <sys/scoket.h>
socket()
int socket(int domain, int type, int protocol);
参数
成功返回文件描述符,错误返回-1
domain:
AF_INET
AF_INET6
AF_NUIX/AF_LOCAL
本地通信
AF_NETLINK
内核间通讯,驱动用
AF_PACKET
原始套接字应用
type:
SOCK_STREAM:流式套接字,TCP
SOCK_DGRAM:数据报套接字,UDP
SOCK_RAW:原始套接字
protocol:
一般填0
原始套接字需要填充,区分IP,或ICMP
bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_taddrlen);
参数
sockfd:通过socket函数拿到的fd
addr:struct sockaddr的结构体变量的地址
//通用结构体
struct sockaddr{
sa_family_t sa_family; //2字节
char sa_data[14]; //14字节
}
struct sockaddr_in{
sa_family_t sin_family; //2字节
in_port_t sin_port; //2字节
struct in_addr sin_addr; //4字节
sin_zero[8];
}
struct in_addr{
unit32_t s_addr; //32位网络字节序的IP,4字节
}
sockaddr_in结构体重包含一个sin_zero[8]的填充位,此填位必须清零
addrlen:地址的长度
如果是IPV6编程,要使用struct scokaddr_in6结构体(man 7 IPV6),通常更通用的方法是通过sturct sockaddr_storage来编程
sendto()
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
参数
const struct sockaddr *dest_addr
通用结构体 struct sockaddr_in
填充对方IP地址和端口号
socklen_t addrlen
地址长度
recvfrom()
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);
参数
struct sockaddr *src_addr
struct sockaddr_in
发送方的IP地址和端口号
socklen_t *addrlen
地址长度