网络编程,也就是建立一个客户端和服务器间的一个socket连接。这篇文掌将介绍一些关于网络编程的函数。
一:TCP 连接示意图
二: UDP连接示意图
三、函数介绍
1、创建一个socket套接字,返回一个文件描述符
int socket(int domain, int type, int protocol)
参数分析:
domain: 协议族名,如AF_INET、AF_PACKET等。详情见文件/usr/include/linux/socket.h。
type: 希望建立连接的类型,可以是tcp(SOCK_STREAM),也可以是udp(SOCK_DGRAM).
protocol:表示该协议族中的那种协议,0表示自动选择。
2、绑定(绑定本地的一个ip和端口)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
参数分析:
socket: socket()函数创建时,返回的一个文件描述符.
address: 一个包含ip和端口的结构体。在通常情况下,使用结构体struct sockaddr_in结构体。赋值后,强制类型转换为struct sockaddr 类型。
address_len: 第二个参数结构体的大小。
结构体内容:
struct sockaddr_in
{
sa_family_t sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[ __SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
struct in_addr
{
__u32 s_addr;
};
使用说明:
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr('192.168.1.177');
server.sin_port = htons(9734);
bind(sockfd, (struct sockaddr *)&server, sizeof(server));
3、设置监听客户端连接的个数
int listen(int sockfd, int backlog);
参数分析:
sockfd: socket()函数返回的文件描述符;
backlog: 设置监听的个数;
4、等待客户端的握手连接, 返回一个用于双方通信的描述符。该函数和connect()对应。
int accept(int socket, struct sockaddr *restrict_address, socklen_t * restrict_address_len);
参数说明:
socket:socket()函数返回的描述符。
restrict_address: 用于存放connect()函数连接时传递过来的客户端struct sockaddr结构体,可以获取对方IP.
restrict_len: 该结构体的大小,也就是sizeof(struct sockaddr);
5、客户端和服务器握手连接的函数
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
参数分析:
sockfd: 客户端socket()函数返回的一个socket描述符;
serv_addr: 用于存放服务器的ip地址和端口号的结构体,和上面的bind()函数一样。
addrlen:结构体的长度。
6、适应于tcp连接的数据交互
6.1、数据接收
ssize_t read(int fildes, void *buf, size_t nbyte)
files:在服务器端是accept()返回的描述符,在客户端表示socket()返回的描述符
buf: 用于保存接受的数据。
nbyte: 表示接受多少长度的字节数
ssize_t recvmsg(int s, struct msghdr *msg, int flags)
s:在服务器端是accept()返回的描述符,在客户端表示socket()返回的描述符。
msg:用于存储发送过来的数据,还有数据长度,以及相关的信息。
flags:接受数据的的标志通常为0。
结构体内容
sasl/sasl.h
struct iovec
{
long iov_len;
char *iov_base;
};
linux/sockt.h
struct msghdr
{
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
__kernel_size_t msg_iovlen; /* Number of blocks */
void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
__kernel_size_t msg_controllen; /* Length of cmsg list */
unsigned msg_flags;
};
使用:
unsigned char buf[100];
struct iovc iov;
struct msghdr msg;
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
recvmsg(fd, &msg, 0);
6.2、发送数据
ssize_t write(int fildes, const void *buf, size_t nbyte);
参数分析:
files: 在服务器端是accept()返回的描述符,在客户端表示socket()返回的描述符。
buf:用于保存发送数据的缓冲区;
nbyte: 发送数据的长度;
ssize_t sendmsg(int s, const struct msghdr *msg, int flags);
s:在服务器端是accept()返回的描述符,在客户端表示socket()返回的描述符。
msg:用于存储发送数据时的数据内容和长度;
flags:发送标志,一般为0;
使用介绍:
unsigned char buf[100];
struct iovc iov;
struct msghdr msg;
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(fd, &msg, 0);
7、适用于udp的数据交互
7.1、接受数据
ssize_t recvfrom(int socket, void *restrict_buffer, size_t length, int flags,
struct sockaddr *restrict_address, socklen_t *restrict_address_len);
参数分析:
socket: 在服务器端是accept()返回的描述符,在客户端表示socket()返回的描述符。
restrict_buf:用于保存接受到的数据;
length:接受数据的长度;
flags:标志位0;
restrict_address: 用于存放对方的地址;
restrict_address_len: 该结构体的长度
发送数据:
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
参数分析:
如recvfrom()
三、一些其他函数
1、int inet_pton(int family,const char * strptr,void * addrptr);
返回:1---成功 0---输入不是有效的表达格式 -1---失败
第一个参数可以是AF_INET或AF_INET6:第二个参数是一个指向点分十进制串的指针:第三个参数是一个指向转换后的网络字节序的二进制值的指针。
使用:
struct sockaddr_in server;
inet_pton(AF_INET, "192.168.1.177", &(server.sin_addr));
2、inet_ntop函数:和inet_pton函数正好相反,inet_ntop函数是将网络字节序二进制值转换成点分十进制串。
3、设置套接字选项
int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t *optlen)
参数详解:
sockfd: socket描述符;
level:
level指定控制套接字的层次.可以取三种值:
1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP选项.
3)IPPROTO_TCP:TCP选项.
optname:指定控制的方式(选项的名称)
optval获得或者是设置套接字选项.根据选项名称的数据类型进行转换
选项名称 说明 数据类型
========================================================================
SOL_SOCKET
------------------------------------------------------------------------
SO_BROADCAST 允许发送广播数据 int
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由 int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
SO_LINGER 延迟关闭连接 struct linger
SO_OOBINLINE 带外数据放入正常数据流 int
SO_RCVBUF 接收缓冲区大小 int
SO_SNDBUF 发送缓冲区大小 int
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SO_REUSERADDR 允许重用本地地址和端口 int
SO_TYPE 获得套接字类型 int
SO_BSDCOMPAT 与BSD系统兼容 int
==========================================================================
IPPROTO_IP
--------------------------------------------------------------------------
IP_HDRINCL 在数据包中包含IP首部 int
IP_OPTINOS IP首部选项 int
IP_TOS 服务类型
IP_TTL 生存时间 int
==========================================================================
IPPRO_TCP
--------------------------------------------------------------------------
TCP_MAXSEG TCP最大数据段的大小 int
TCP_NODELAY 不使用Nagle算法 int
=========================================================================