伯克利套接字(Berkeley sockets),也称为BSD Socket。伯克利套接字的应用编程接口(API)是采用C语言的进程间通信的库,经常用在计算机网络间的通信。 BSD Socket的应用编程接口已经是网络套接字的抽象标准。大多数其他程序语言使用一种相似的编程接口。它最初是由加州伯克利大学为Unix系统开发出来的。所有现代的操作系统都实现了伯克利套接字接口,因为它已经是连接互联网的标准接口了。
socket()
创造某种类型的套接字,分配一些系统资源,用返回的整数识别。bind()
一般是用在服务器这边,和一个套接字地址结构相连,比如说是一个特定的本地端口号和一个IP地址。listen()
用在服务器一边,导致一个绑定的TCP套接字进入监听状态。connect()
用在客户机这边,给套接字分配一个空闲的端口号。比如说一个TCP套接字,它会试图建立一个新的TCP连接。accept()
用在服务器这边。从客户机那接受请求试图创造一个新的TCP连接,并把一个套接字和这个连接相联系起来。send()
and recv()
, or write()
and read()
, or sendto()
and recvfrom()
用来接收和发送数据。close()
当套接字的引用计数为0的时候才会引发TCP的四次挥手,关闭连接,系统释放资源。------- 不可对某个socket连续调用两次close,否则第二次调用会出现释放未分配的内存问题(野指针)(在LWIP下测试得出的结论)。个人想法:应该在close函数里面把socket置成某个数,这样每次进入close,如果socket等于某个数,表示已经close过,直接函数返回。
gethostbyname()
and gethostbyaddr()
用来解析主机名和地址。select()
------ 用来获取指定套接字的状态(可读、可写或者出错)poll()
is used to check on the state of a socket in a set of sockets. The set can be tested to see if any socket can be written to, read from or if an error occurred.getsockopt()
------ 获得套接字的属性,有些属性的开关在 opt.h 和 lwipopts.hsetsockopt()
------ 设置套接字的属性,有些属性的开关在 opt.h 和 lwipopts.h
这四个函数用在 TCP 通信中
recv和send函数提供了和read和write差不多的功能.不过它们提供了第四个参数来控制读写操作
int recv(int sockfd,void *buf,int len,int flags) int send(int sockfd,void *buf,int len,int flags)
对于send(),flags取值有: 0: 与write()无异,阻塞操作 MSG_DONTROUTE:告诉内核,目标主机在本地网络,不用查路由表 MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式 MSG_OOB:指明发送的是带外信息 对于recv(),flags取值有: 0:与read()无异,阻塞操作 MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式 MSG_OOB:指明发送的是带外信息 MSG_PEEK:表示只是从系统缓冲区中读取内容,而不清除系统缓冲区的内容.这样下次读的时候,仍然是一样的内容.一般在有多个进程读写数据时可以使用这个标志. MSG_WAITALL:通知内核直到读到请求的数据字节数时,或者发送了错误才返回。 对于接收数据函数的返回值: 大于0:读到数据的字节数 等于0:套接字关闭,读到FIN 小于0: EINTR:表示操作被中断,下次可以继续读取,忽视这个返回值 EWOULDBLOCK(EAGAIN):当非阻塞读取时,没有数据可读,返回此操作码 ECONNRESET:对方发送RST ...... 对于发送数据函数的返回值: 大于0:成功发送数据的字节数 等于0:套接字关闭 小于0: EINTR:表示连接正常,操作被中断,此次数据发送失败,下次可以继续发送 EWOULDBLOCK(EAGAIN):表示连接正常,但发送缓冲区没有空间,此次数据发送失败,下次可以继续发送 ...... 注:不能通过 shutdown 读写通道主动退出服务器的阻塞read(),但是可以主动退出退出客户端的阻塞read(),ESP8266测试得到
这两个函数用在UDP通信的接收和发送
int recefrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
int sendto(int sockfd, const void *buf, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
int socket(int domain, int type, int protocol);
socket()
为通信创造一个端点并返回一个文件描述符。 socket()
有三个参数:
PF_INET
(AF_INET)是IPv4 PF_INET6
是 IPv6.SOCK_STREAM
(Stream Socket)SOCK_DGRAM
(Datagram Socket)SOCK_RAW
(Raw Socket)。IPPROTO_TCP
, IPPROTO_UDP
, IPPROTO_UDPLITE、IPPROTO_ICMP
。如果 domain
和 type
已经确定唯一的协议,“0(IPPROTO_IP
)
” 可以用来表示选择一个默认的协议。tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); // 由于 PF_INET 和 SOCK_STREAM 已经可以确认是使用 IPPROTO_TCP,所以第三个参数填什么都不影响 udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); // PF_INET 和 SOCK_DGRAM 表明使用 IPPROTO_UDP 或 IPPROTO_UDPLITE 其中一种协议,第三个参数填的不是 IPPROTO_UDPLITE 都是IPPROTO_UDP
如果出错返回-1,否则返回一个代表文件描述符的整数(一般有个宏NUM_SOCKETS规定一共可以创建多少个socket,所以socket()创建成功返回的整数范围为0~NUM_SOCKETS-1,而且是从小到大返回)
bind()
给套接字分配一个地址。当使用 socket()
创造一个套接字时, 只是给定了协议族,并没有分配地址。在套接字能够接受来自其他主机的连接前,必须用bind()给它绑定一个地址。 bind()
由三个参数:
sockfd
, 代表socket的文件描述符。my_addr
, 指向 sockaddr
结构体的指针,代表要绑定的地址 。addrlen
, 是sockaddr结构体的大小。Bind()返回0表示成功,错误返回-1。
函数原型:
int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
一旦一个套接字和一个地址联系之后,listen()
监听到来的连接。但是这只适用于对面向连接的模式,例如 套接字类型是 (SOCK_STREAM
, SOCK_SEQPACKET
)。listen()需要两个参数:
sockfd:
一个有效的套接字描述符。backlog:accept 队列大小。当服务器接收到第三次握手后将连接放入这个队列中,直到被 accept 处理才清除,当 accept 队列满了之后,即使 client 继续向 server 发送 ACK 包,也不会被响应,此时 ListenOverflows+1,同时 server 通过 /proc/sys/net/ipv4/tcp_abort_on_overflow(linux kernel 2.2 之后)来决定如何返回,0表示直接丢弃该 ACK,1表示发送 RST 通知 client;相应的,client 则会分别返回 read timeout 或者 connection reset by peer。参考下图。
一旦连接被接受,返回0表示成功,错误返回-1。
函数原型:
int listen(int sockfd, int backlog);
当应用程序监听来自其他主机的面对数据流的连接时,通过事件(比如Unix select()系统调用)通知它。必须用accept()
函数初始化连接。 Accept() 为每个连接创立新的套接字并从监听队列中移除这个连接。它使用如下参数:
sockfd
,监听的套接字描述符cliaddr
, 指向sockaddr 结构体的指针,客户机地址信息。addrlen
,指向 socklen_t
的指针,确定客户机地址结构体的大小 。返回新的套接字描述符,出错返回-1。和客户端的通信是通过这个套接字。假如是 sockfd(服务器套接字,accept 第一个参数) 0,accpet 返回的是 1,递增。可以在没关闭 accept 返回的套接字之前关闭 accept 的套接字,这样防止新的客户端连上。但是有个问题,如果关闭服务器套接字,accept 返回一个套接字是1,用 select 函数的第一个参数填套接字总数,现在的总是是1,而唯一个套接字的值是1(不是0),所以 select 会返回小于0,不能正常使用 select 函数。
Datagram 套接字不要求用accept()处理,因为接收方可能用监听套接字立即处理这个请求。
函数原型:
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
注:不能通过 close() 或者 shutdown() 主动退出 accept() 阻塞,ESP8266测试得出。
connect()
系统调用为一个套接字设置连接,参数有文件描述符和主机地址。
函数原型:
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
close()函数只是将这个套接字引用计数减1,就像rm一样,删除一个文件时只是移除一个硬链接数,只有这个套接字的所有引用计数减到0,套接字描述符才会真的被关闭,才会开始后续的四次挥手。
关于引用计数:操作系统创建子进程时,子进程将继承父进程打开的套接字,父子进程拥有对该套接字同样的访问权,系统对每个套接字的引用进行计数,每增加一个进程访问套接字,计数加1,当进程完成对套接字的使用时,对套接字的使用调用 close 进行关闭,close 调用将减少套接字的引用计数,并且在计数值为0时删除该套接字
SO_LINGER选项对close()的行为有影响
SO_LINGER 的 I_onoff 为0(默认情况):
在套接字上不能再发出发送或接收请求,套接字发送缓冲区中的内容被发送到对端,如果描述符引用计数变为0,在发送完发送缓冲区的数据后,后跟正常的TCP连接终止序列(即发送FIN),套接字接收缓冲区中的内容被丢弃
SO_LINGER 的 l_onoff = 1,l_linger = 0:
在套接字上不能再发出发送或接收请求,如果描述符引用计数变为0,RST被发送到对端,连接的状态被置为CLOSED(没有TIME_WAIT状态),套接字发送缓冲区和接收缓冲区中的内容被丢弃;
可以指定关闭读通道、写通道或者读写通道。
调用了shutdown()的读通道,不会引发四次挥手,但是执行read()会退出阻塞,返回小于0的数,然后再close()引发四次挥手,释放资源。
特别强调:执行 shutdown() 后执行 close(),然后再执行read()会阻塞,永远的阻塞。。。
gethostbyname()
和 gethostbyaddr()
函数是用来解析主机名和地址的。可能会使用DNS服务或者本地主机上的其他解析机制(例如查询/etc/hosts)。返回一个指向 struct hostent的指针,这个结构体描述一个IP主机。函数使用如下参数:
出错返回NULL指针,可以通过检查 h_errno 来确定是临时错误还是未知主机。正确则返回一个有效的 struct hostent *。
这些函数并不是伯克利套接字严格的组成部分。这些函数可能是过时了,新函数是 getaddrinfo() and getnameinfo(), 这些新函数是基于addrinfo数据结构。
函数原型:
struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const void *addr, int len, int type);
int setsockopt( int socket, int level, int option_name, const void *option_value, size_t option_len);
sockfd: 套接字
level: 协议层(SOL_SOCKET、IPPROTO_IP、IPPRO_TCP)
opt_name: 选项名,每一个协议层都有其一些固定的选项名,
option_value: 缓冲区,setsockopt() 是指向将要存放的地址,getsockopt() 是指向目前存放信息的地址
option_len: 缓冲区大小长度
在 socket.h 有 level 和 opt_name 的介绍
SOL_SOCKET层,有如下选项:
opt_name | 说明 | option_value类型 |
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_TCP层,有如下选型:
TCP_NODELAY
TCP_KEEPIDLE(设置多久没接收到数据开始发送keepalive包)
TCP_KEEPINTVL(设置每个keepalive包的间隔时间)
TCP_KEEPCNT(设置发送多少个keepalive包)
......
ntohs(n) //n为16位数据类型,网络字节顺序到主机字节顺序的转换
htons(n) //n为16位数据类型,主机字节顺序到网络字节顺序的转换
ntohl(n) //n为32位数据类型,网络字节顺序到主机字节顺序的转换
htonl(n) //n为32位数据类型,主机字节顺序到网络字节顺序的转换
网络字节顺序采用大端模式进行编址,而主机字节顺序根据处理器的不同而不同,如PowerPC处理器使用大端模式,而Pentuim处理器使用小端模式。大端模式处理器的字节序到网络字节序不需要转换,此时ntohs(n)=n,ntohl(n) = n;而小端模式处理器的字节序到网络字节必须要进行转换
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout)
本函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用结构体 fd_set 来表示一组等待检查的套接口。在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目,0表示超时,-1表示出错。有一组宏可用于对 fd_set 的操作(宏的功能有:把套接口放入 fd_set 结构、清除 fd_set 结构中的某个套接口、检查否个套接口是否可读可写等)
maxfdp1:等于创建成功的socket个数,socket()成功返回的整数范围为0~NUM_SOCKETS-1,NUM_SOCKETS为最多能创建的个数,所以maxfdp1一般取值为socket()返回的最大值+1
readset:(可选)指针,指向一组等待可读性检查的套接口。如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成。对其他套接口而言,可读性意味着有数据供读取,于是recv()或recvfrom()操作均能无阻塞完成
writeset:(可选)指针,指向一组等待可写性检查的套接口。如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立。如果套接口并未处于connect()调用中,可写性意味着send()和sendto()调用将无阻塞完成
exceptset:(可选)指针,指向一组等待错误检查的套接口。
timeout:select()最多等待时间,对阻塞操作则为NULL
不需要查看的形参可以设为NULL
返回值:负值:select错误,正值:可读可写套接口数目,0:等待超时,没有可读写或错误的文件
判读:通过宏 FD_ISSET、&readset(宏参数) 和 具体某个描述符(宏参数) 判断该描述符是否可读;通过宏 FD_ISSET、&writeset(宏参数) 和 具体某个描述符(宏参数) 判断该描述符是否可写;
int fcntl(int s, int cmd, int val);
s 为要设置的socket,cmd 是要进行什么操作,val 是操作所需要的参数
返回值:成功取决于cmd,失败返回-1
函数有下面5种功能:
在socket编程中使用 fcntl() 设置 sockfd 为非阻塞模式,则之后的connect、accept、recv、recvfrom等函数便失去了阻塞功能,变成了非阻塞函数。
用以下方法将socket设置为非阻塞方式:
int flags = fcntl(socket, F_GETFL, 0); fcntl(socket, F_SETFL, flags | O_NONBLOCK);
将非阻塞的设置回阻塞可以用以下方式:
int flags = fcntl(socket, F_GETFL, 0); fcntl(socket, F_SETFL, flags & ~O_NONBLOCK);
int ioctl(int s, long request, void *argp);
ioctl 是 input output control 的简写,控制I/O设备, 提供了一种获得设备信息和向设备发送控制参数的手段
返回值:成功返回0,出错返回-1
第一个参数:指示某个文件描述符(当然也包括 套接口描述符)
第二个参数:request 指示要ioctl执行的操作
第三个参数:总是某种指针,具体的指向类型依赖于 request 参数
我们可以把和网络相关的请求(request)划分为6 类:
套接口操作
文件操作
接口操作
ARP 高速缓存操作
路由表操作
流系统
下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
类别 |
Request |
说明 |
数据类型 |
套 |
SIOCATMARK |
是否位于带外标记 |
int |
文 |
FIONBIN |
设置/ 清除非阻塞I/O 标志 |
int |
接 |
SIOCGIFCONF |
获取所有接口的清单 |
struct ifconf |
ARP |
SIOCSARP |
创建/ 修改ARP 表项 |
struct arpreq |
路 |
SIOCADDRT |
增加路径 |
struct rtentry |
流 |
I_xxx |
|
|
inet_ntoa()将一个 32bits 无符号整数转换为点分十进制IP格式的字符串。inet_addr()正好相反,inet_addr可以判断形参是否IP格式的字符串,不是返回0xFFFFFFFF
char* inet_ntoa (struct in_addr addr);
结构体in_addr唯一一个成员就是32bits 无符号整数
int inet_pton(int af, const char *src, void *dst);
af 是地址簇,比如 af=AF_INET,AF_INET(又称 PF_INET)是 IPv4 网络协议的套接字类型
指针 src 指向十进制IP格式的字符串
指针 dst 指向 32bits 无符号整数,即要得到的数据
IP4_ADDR(ipaddr, a,b,c,d)
ipaddr是一个结构体(struct ip_addr),含有成员变量addr
PF_INET(AF_INET):IPv4(网际层)
PF_INET6(AF_INET6):IPv6(网际层)
SOCK_STREAM:设置套接字类型为流套接字,流套接字协议只有一个,即 IPPROTO_TCP(传输层)
SOCK_DGRAM:设置套接字类型为数据报套接字,数据报套接字协议有两个个,即 IPPROTO_UDP 和 IPPROTO_UDPLITE(传输层)
SOCK_RAW:设置套接字类型为原始套接字
原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW
套接字API是Unix网络的通用接口,允许使用各种网络协议和地址。
下面列出了一些例子,在现在的 Linux 和BSD中一般都已经实现了。
PF_LOCAL, PF_UNIX, PF_FILE Local to host (pipes and file-domain) PF_INET IP protocol family PF_AX25 Amateur Radio AX.25 PF_IPX Novell Internet Protocol PF_APPLETALK Appletalk DDP PF_NETROM Amateur radio NetROM PF_BRIDGE Multiprotocol bridge PF_ATMPVC ATM PVCs PF_X25 Reserved for X.25 project PF_INET6 IP version 6 PF_ROSE Amateur Radio X.25 PLP PF_DECnet Reserved for DECnet project PF_NETBEUI Reserved for 802.2LLC project PF_SECURITY Security callback pseudo AF PF_KEY PF_KEY key management API PF_NETLINK, PF_ROUTE routing API PF_PACKET Packet family PF_ASH Ash PF_ECONET Acorn Econet PF_ATMSVC ATM SVCs PF_SNA Linux SNA Project PF_IRDA IRDA sockets PF_PPPOX PPPoX sockets PF_WANPIPE Wanpipe API sockets PF_BLUETOOTH Bluetooth sockets
mojitomojito jar 包 下载 : http://download.csdn.net/detail/richard_jason/9660916mojito是一个简单而灵活的测试框架,最初开发它是为了解决OpenSearch前端测试中遇到的一些问题,但是随着mojito的开发,我们发现它可以被应用在更广泛的范围里。mojito目前只是测试工具,而非测试服务。用户
原标题:详解MySQL|你不知道的新特性-MySQL8.0的正则替换 爱可生 MySQL 一直以来都支持正则匹配,不过对于正则替换则一直到MySQL 8.0 才支持。对于这类场景,以前要么在MySQL端处理,要么把数据拿出来在应用端处理。比如我想把表y1的列str1的出现第3个action的子 串替换成dble,怎么实现?1. 自己写SQL层的存储函数。代码如下写死了3个,没有优化,仅仅作为演示,..._mysql set @s=(1,2)
04 | HTTP世界全览(下):与HTTP相关的各种协议TCP/IP和HTTP的关系HTTP是应用层协议,构建在TCP/IP之上。TCP为HTTP提供了可靠的数据传输通道,IP解决网际间寻址路由问题,所以HTTP更准确应称为HTTPover TCP/IP。DNS,URI和HTTP的关系DNS+URI为HTTP提供定位网络资源的能力。DNS提供域名到IP的映射,可以定位到主机。URI可以定位到主机上的具体资源。HTTPS和HTTP的关系HTTPS = HTTP+TLS,是安全的H
设某回归任务的输入包含两个变量,将它们的值视为平面上点的坐标。如图2.1所示,灰点代表训练数据中的输入,白点代表输出待预测的输入。假如采用2.3节介绍的平均值法,当白点与黑点重合时,因为在该处只有一个训练实例,所以平均值不能很好地代表期望值;而当白点处于更有可能的其他位置时,因为在该处没有训练实例,无法预测输出值。为走出此困境,自然的想法是,在计算平均值时,扩大取其输出的实例的范围。假设输出待预测的输入为x,原来要求找到训练数据中输入等于x的实例,现在则放宽到所有输入处于x的某邻域的实例。在图2.1中,以白_k近邻算法回归预测
k近邻法可用于分类和回归,是最简单的机器学习方法,是懒惰学习的著名代表。算法原理:给定一个训练数据集(类别确定),对于输入的实例,在训练数据集中寻找到与输入实例最接近的k个实例。k个实例中多数类别即为输入实例的类别。
回归预测 | MATLAB实现KNN(K近邻)多输入单输出回归预测_knn回归 matlab
预编译语言:less sass style提供些css的速度less:less is more,than css.少及多,比cssless1、类似于jqurey2、动态样式语言,属于css预处理语言的一种,类似于css语法,为css赋予了动态语言的特点,如变量、函数、继承、运算等,更方便css的编写和维护。3、后缀.lesskoala:less/sass编译工具4、多行注释才会被编...
View Code #include"iostream"using namespace std;int a[1001],b[1001];int used[1001];int n;int i,j,q,t;void Init(){ for(i=1;i<40;i++) b[i]=1; for(i=2;i<40;i++) { for(j=2;j...
树形选择排序又名锦标赛排序,算法思想与体育比赛类似, 首先将n个数据元素两两分组,分别按关键字进行比较,得到n/2个比较的优胜者(关键字小者),作为第一步比较的结果保留下来, 然后对这n/2个数据元素再两两分组,分别按关键字进行比较,如此重复,直到选出一个关键字最小的数据元素为止。树形选择排序构成的树是满二叉树。算法步骤:1.先获取需要排序的n个数据对象。2.将n个数据对象用数_list树形排序
支付回调中调用接口不起作用,接口未被调用回调函数的作用域问题作用域问题——回调函数中的作用域已经脱离了调用函数了,因此需要在回调函数外边把this赋给一个新的变量才可以了。// An highlighted blockvar that = this;..._调用建行支付回调接口 https一直不行
表单是 UI 界面中最为常见的元素,它通常是用来搜集和呈现一些数据、信息和特定的字段。在现实世界中,印刷的表格存在的时间更为久远,它们身上有很多设计可以作为重要的参考,帮助我们优化 UI 中的表单元素。 一、文本框剖析 文本框允许用户在界面中输入文本。它们通常显示在表单和对话框中。文本字段组件设计应为交互提供明确的可见性,使字段在布局中好发现,高效填充且容易理解。 这些是基本文本字段的重要元素: 1.容器-可交互输入文本的区域 2.输入文本-输入文...
1、系统环境查看cat /etc/redhat-release2、安装yum install mysql#看上面提示,安装的是mariadbyum install mysql-server#no such commandCentos7中将Mysql数据库软件从默认程序列表中移除了,用mariadb代替了2、安装(new)-ivh:i指将安装指的的rmp软件包,v表示安装时的详细信...