Linux中的网络编程通过Socket(套接字)实现,
Socket是一种文件描述符.
Socket函数原型:
Socket创建一个通信端点 | ||
所需头文件 | #include <sys/socket.h> | |
函数说明 | 创建一个通信端点并返回一个文件描述符 | |
函数原型 | int Socket(int domain,int type,int protocol); | |
函数传入值 | domain | domain参数指定一个通信域; 这个选择将用于通信协议族. 目前理解格式包括: Name Purpose Man page |
type | 指定通信类型. 目前定义类型: SOCK_STREAM :提供sequenced(序列化的),reliable(可靠的),two-way(双向的),connection-based(基于连接的) byte streams. 可支持带外数据传输机制. out—of—band data(带外数据,有时也称为加速数据(expedited data)) . 它使用TCP协议. SOCK_DGRAM:支持数据报(一个固定最大长度不可靠的无连接的消息) 它使用UDP协议. SOCK_SEQPACKET: 为固定最大长度的数据报提供一个序列化的可靠的双向基于连接的数据传 输路径;随着每一个系统调用,一个用户必须读取一个完整包 SOCK_RAW:提供原始网络协议套接字. SOCK_RDM: 在不能保证运作时,提供一个可靠的数据包层 SOCK_PACKET: 在新版本中淘汰或将要不用. | |
protocol | protocol参数指定一个和socket被用在一起的特殊协议.在一个给定的协议族之内,通常只有一 个单协议存在支持一个特殊的socket类型,在这种情况下protocol可以指定为0.然而,可能存在很 多协议,在这种情况下一个特殊协议必须在这种方式下被指定.protocol number用来指定"通信域"在哪发生通讯. | |
| | |
| ||
| ||
函数返回值 | 成功:返回新的socket描述符 | |
错误:-1 | ||
错误代码 | EACCES: 允许创建一个指定类型的and/or协议的socket被拒绝. EAFNOSUPPORT: 执行不支持指定地址族. EINVAL:不知道协议,或者协议族无效. EINVAL:type参数是无效标志. EMFILE:进程文件表溢出. ENFILE: 达到系统限制打开的文件总数. ENOBUFS or ENOMEN: 内存不足.在足够的资源被释放之前socket不能被创建 EPROTONOSUPPORT: 在当前domain中协议类型或指定协议不被支持. |
Socket函数具体解释:点击打开链接
bind 函数原型:
bind绑定scoket的名字 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 绑定地址 | |
函数原型 | int bind(int sockfd,const struct sockaddr *addr, socklen_t addrlen); | |
函数传入值 | sockfd | 指定绑定的socket文件描述符 |
addr | 指定绑定的地址 | |
sddrlen | 指定地址结构的大小 | |
| | |
| ||
| ||
函数返回值 | 成功:0 | |
错误:返回-1 | ||
错误代码 | EACCES:地址受保护,并且用户不是超级用户 EADDRINUSE:获取的地址已经被占用 EBADF:sockfd不是一个有效的描述符 EINVAL:scoket已经被绑定到一个地址上 ENOTSOCK:sockfd是一个文件描述符,但不是一个socket |
网络地址结构:
转换IP:
字节序转换:
htons,htonl发送时使用
ntohs,ntohl接收时使用
IP与主机
connect函数原型:
connect开启一个socket连接 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 开启一个socket连接 | |
函数原型 | int connect(int sockfd,const struct sockaddr *addr, socklen_t addrlen); | |
函数传入值 | sockfd | 指定绑定的socket文件描述符 |
addr | 指定连接的地址 | |
addrlen | 指定地址结构的大小 | |
| | |
| ||
| ||
函数返回值 | 成功:0 | |
错误:返回-1 | ||
错误代码 | EACCES:对于Unix域Socket而言,被pathname识别的socket:在socket文件上写权限是禁止的, 对目录中的路径前缀进行搜索是禁止的. EACCES,EPERM:用户试图连接一个广播地址但是socket的广播标志位并没有使用,或者是因为本地防火墙规则原因导致请求失败. EADDRINUSE:本地地址已经被使用. EAFNOSUPPORT:在地址sa_family域中并没有传入的正确地址族 EAGAIN:没有足够的本地端口或者是在路由缓存中没有足够的入口 |
connect函数具体解释:点击打开链接
listen函数原型:
listen:监听socket的连接 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 监听socket的连接 | |
函数原型 | int listen(int sockfd,int backlog); | |
函数传入值 | sockfd | 指定要监听的socket的 |
涉及SOCK_STREAM或SOCK_SEQPACKET的socket的文件描述符 | ||
backlog | 定义监听连接队列的最大个数 | |
| ||
| ||
函数返回值 | 成功:0 | |
出错:返回-1 | ||
| ||
错误代码 | EADDRINUSE: 其它的socket已经监听在相同的端口上 EBADF:sockfd指定的参数不是一个有效的描述符 ENOTSOCKT:sockfd指定的参数不是一个socket EOPNOTSUPP:socket不是一个支持listen()操作的类型 ...... |
accept函数原型:
accept接收一个socket连接 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 接收一个socket连接 | |
函数原型 | int accept(int sockfd,struct sockaddr *addr, socklen_t addrlen); | |
函数传入值 | sockfd | 指定接收的socket文件描述符 |
addr | 指定接收的地址 | |
sddrlen | 指定地址结构的大小 | |
| | |
| ||
| ||
函数返回值 | 成功:返回一个socket被接收的非负整数的描述符 | |
错误:返回-1 | ||
错误代码 | EAGAIN or EWOULDBLOCK:socket 被标志为非阻塞和没有连接是被当前接收. EBAND:描述符无效 ECONNABORTED:连接已经被终止 EFAULT:addr参数在用户地址空间是不可写的部分 .... |
send函数原型:
send:在socket上发送消息 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 给其它的socket传送一条消息 | |
函数原型 | ssize_t send(int sockfd,const void *buf,size_t len,int flags); | |
函数传入值 | sockfd | 指定发送socket的文件描述符 |
buf | 存储要发送的信息 | |
len | 要发送信息的长度 | |
flags | MSG_CONFIRM:(从Linux 2.3.15之后开始支持) 告诉连接层之前的处理发生了:你已经从别处获得了成功的应答. 如果连接层没从别处获得成功的应答,那么连接层就会定期的再 再次探测它的邻居(如通过ARP的单播).只有在SOCK_DRAM和 SOCK_RAM的socket上有效,当前只有IPv4 IPv6上实现. MSG_DONTROUTE: 不要用网关发出数据包,仅仅通过直接拦截的网络向主机发送. 这经常用在诊断或者路由程序中.这仅仅是为了路由协议族定义的, socket的包不使用. MSG_DONTWAIT:(从Linux 2.2之后开始支持) 是能够非阻塞操作,如果操作阻塞的话,返回EAGAIN或EWOULDBLOCK (也可以使用O_NONBLOCK在fcntl(2)的 F_SETFL打开). MSG_EOR(从Linux 2.2之后开始支持) 终结了一个记录(当支持这个想法的时候,就和SOCK_SEQPACKET的socket类型一样了) MSG_MORE(从Linux 2.4.4之后开始支持) 调用者还有更多的数据要发送.这个标志位是在TCP的socket上用来获得TCP_CORK socket一样 的效果的(参见tcp(7)),唯一的不同是这个标志位可以在预先调用的基础上设置. 在Linux 2.6之前,这个标志位也被UDP支持,并通知内核将在调用中所有设置这个标志位的数据 打包为一个单独的数据报,这个数据报仅仅当调用生效的时候而没有设置这个标志的时候回发送. (参见UDP-CORK在udp(7)的选项中有描述). MSG_NOSIGNAL(从Linux 2.2 之后开始支持) 要求在面向流的socket上当错误发生的时候不发送SIGPIPE这个信号,当别的终端破坏这个连接的 时候.EPIPE错误仍然被返回. MSG_OOB 支持这种情况的话会在socket上发送越界数据(如 SOCK_STREAM),与之反应的协议也要支持越界数据. |
| ||
函数返回值 | 成功:返回发送的字符数 | |
错误:返回-1 | ||
错误代码 | EACCES (在UNIX下通过路径定义的socket域)在目的地址的socket写权限是禁止的,或者是在路径的目录前缀搜索权限是禁止的
EAGAIN or EWOULDBLOCK:
socket标记俄日非阻塞但是要求的操作阻塞了它.POSIZ. 1-2001 在这种情况下允许返回这两者中的任何一个,并不需要两者有相同的值,所以一个可移植的程序应该对这两种可能性都进行检查
EBADF: 无效的描述符.
ECONNRESET:对方重置了连接.
注:比较容易出现这种情况的原因:
①: 服务器的并发连接数超过了其承载量,服务器将会其中一些连接Down掉;
②: 客户关掉了浏览器,而服务器还在给客户端发送数据;(在关闭IE的时候,设备的发送端确实会返回这个错误)
.....
|
send,sendto,sendmsg函数具体说明:点击打开链接
recv函数原型:
recv从socket接受消息 | ||
所需头文件 | #include <sys/types.h> #include <sys/socket.h> | |
函数说明 | 从socket接收消息 | |
函数原型 | ssize_t recv(int sockfd,void *buf,size_t len,int flag); | |
函数传入值 | sockfd | 指定接收的socket文件描述符 |
buf | 指定接收的内容存储到的位置 | |
len | 指定接收内容的大小 | |
flag | MSG_CMSG_CLOEXEC(recvmsg()专用,从Linux 2.6.23后开始支持) 对文件描述符设置close-on-exec标志位,这个标志位是通过UNIX域文件描述符(设置了SGM_RIGHTS选项)接收的.基于相同的原因,这个标志位在open(2)的O_CLOEXEC 标志位上是有用的. | |
MSG_DONTWAIT(从Liunx 2.2 开始支持) 使能非阻塞选项.如果操作阻塞的话,那么调用就会失败,error为EAGAIN或者EWOULDBLOCK(这个标志位也能够在fcntl(2)中使用O_NOBLOCK使能). | ||
MSG_ERRQUEUE(从LInux 2.2 开始支持) 这个标志位指定队列的错误号应该从一个错误队列接收.错误是通过协议(对IPv4是IP_RECVERR)类型的额外信息传递的.用户应该提供一个足够大小的缓存.在cmsq(3)和 ip(7)中查看更多的细节.原始包的载荷造成的错误和正常数据一样通过msg_iovec传递. 数据报的原目的地址造成的错误由msg_name提供. ..... | ||
函数返回值 | 成功:返回已经接收的字节数 | |
错误:返回-1 .如果返回0,说明节点被有序的关闭了 | ||
错误代码 | EACCES:对于Unix域Socket而言,被pathname识别的socket:在socket文件上写权限是禁止的, 对目录中的路径前缀进行搜索是禁止的. EACCES,EPERM:用户试图连接一个广播地址但是socket的广播标志位并没有使用,或者是因为本地防火墙规则原因导致请求失败. EADDRINUSE:本地地址已经被使用. EAFNOSUPPORT:在地址sa_family域中并没有传入的正确地址族 EAGAIN:没有足够的本地端口或者是在路由缓存中没有足够的入口 |
recv,recvfrom,recvmsg具体解释:点击打开链接