UNIX(网络编程-基本用法):04---socket、bind、connect、listen、accept、close
一、socket()函数
#include<sys/types.h>
#include<sys/socket.h>
int socket(int protofamily, int type, int protocol);
- 参数1:即协议域,又称为协议族(family)
域参数指定通信域;这将选择用于通信的协议系列。这些族在<sys/socket.h>中定义
AF_INET 用ipv4地址(32位的)与端口号(16位的)的组合 AF_INET6 IPV6的 AF_LOCAL/或者AF_UNIX
(Unix域socket)用一个绝对路径名作为地址。本地通信 AF_ROUTE 路由套接字 AF_IPX IPX-Novell协议 AF_PACKET 低层包接口包,支持对数据链路的访问 AF_NETLINK 内核用户界面设备 AF_KEY 比较新,支持基于加密的安全性
- 参数2:指定socket类型,与第三个参数有关
套接字具有指定的类型,该类型指定通信语义
并不是所有的协议族都实现了这些协议类型,例如,AF_INET协议族就没有实现SOCK_SEQPACKET协议类型。
SOCK_STREAM 字节流套接字。提供序列化的、可靠的、双向连接的字节流。支持带外数据传输(TCP使用) SOCK_DGRAM 数据报套接字。(UDP使用)支持数据报(固定最大长度的无连接、不可靠的消息) SOCK_RAW 原始套接字。RAW类型,提供原始网络协议访问 SOCK_RDM 提供了一个不保证排序的可靠数据报层。不过可能数据会有乱序 SOCK_PACKET 专用类型。不能在通用程序中使用,它直接从设备驱动接受数据 SOCK_SEQPACKET 有序分组套接字。序列化包,提供一个序列化的、可靠的、双向的基本连接的数据传输通道,数据长度定常。每次调用读系统调用时数据需要将全部数据读出
- 参数3:指定协议类型
参数2的socket类型都有一个默认的协议,如果想使用默认的协议,参数3填0即可
IPPROTO_TCP TCP传输协议(SOCK_STRAM默认使用) IPPTOTO_UDP UDP传输协议(SOCK_DGRAM默认使用) IPPROTO_SCTP STCP传输协议 IPPROTO_TIPC TIPC传输协议
返回值:
- socket创建成功:返回一个socket描述符(sockfd),这个描述字不是固定的,为int类型
- socket创建失败:返回-1,并设置errno变量的值
AF_XXX与PF_XXX的区别
- 在大部分情况下,使用是相同的
二、connect()函数
- 功能:客户端通过调用connect函数来建立与服务器的连接
#include<sys/types.h>
#include<sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t a ddrlen);
参数:
- 参数1:socket描述符(那一个套接字发出去的连接请求)
- 参数2:要连接的套接字地址结构体
- 参数3:对应于参数2的结构体大小
返回值:
- 建立成功:成功返回0
- 建立失败:返回-1,并设置errno变量的值
connect出错的几种情况:
注意事项:
三、bind()函数
- 功能:把一个本地协议地址赋予给一个套接字
#include<sys/types.h>
#include<sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
- 参数1: socket描述符(绑定到哪一个套接字上面)
- 参数2:指向于一个特定协议的结构体指针
- 参数3:对应参数2的结构体长度
返回值:
- 建立成功:成功返回0
- 建立失败:返回-1,并设置errno变量的值
注意事项:
- 套接字要绑定的地址,地址的内容可以绑定或不绑定、或只绑定其中的一部分地址信息
如果不绑定端口,则系统默认给予一个端口:
如果不绑定IP地址:
总结
四、listen()函数
- 功能:作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求
#include<sys/types.h>
#include<sys/socket.h>
int listen(int sockfd, int backlog);
参数:
- 参数1:监听的socket描述符
- 参数2:套接字排队的最大数目
返回值:
- 建立成功:成功返回0
- 建立失败:返回-1,并设置errno变量的值
- 参数2详解:
- 参数2的设定:
void Listen(int fd,int backlog) { char *ptr; if((ptr=getenv("LISTENQ"))!=NULL) backlog=atoi(ptr); if(listen(fd,backlog)<0) perror("listen error"); }
connect的过程:
重传机制:
五、accept函数
- 功能:由TCP服务器调用,用于从已完成连接队列头获取一个套接字。如果队列为空,进程就被投入睡眠(假设套接字默认为阻塞方式)
#include<sys/socket.h>
#include<sys/types.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
- 参数1:监听套接字描述符(哪一个套接字在接收)
- 参数2:一个协议地址结构体,用来保存已连接的对端进程(客户)的地址
- 参数3:对应于参数2的地址结构体大小指针
返回值:
- 接收成功:返回由内核自动生成的一个全新的描述符,代表TCP客户端
- 接收失败:返回-1
注意:
- 如果我们对客户端的地址不感兴趣,则参数2和参数3可以设置为空
六、close()函数
- 关闭相应的socket描述符
#include <unistd.h>
int close(int fd);
参数:
- 对应的socket描述符
返回值:
- 成功:返回0
- 出错:返回-1