最常用的BSD API函数:
socket:创建一个插口(socket)
bind:将本地端口号和IP地址绑定到插口上
listen:TCP监听
accept:TCP监听接受处理
connect:TCP客户端连接
select:特殊插口设置
send/sendto:发送数据包到已连接/未连接插口上
recv/recvfrom:接收数据包从已连接/未连接插口上
getsockopt/setsockopt:获取/改变插口选项
getpeername/getsockname:获取远端/本地地址信息
close:关闭插口
shutdown:按设置关闭插口
gethostbyname/gethostbyaddr:地址域名映射
read:从插口缓存读数据
write:想插口缓存写数据
-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
#include
#include
int socket( int domain, int type, int protocol );
创建通讯用的“插口”(插口socket可以理解为IP地址和端口号组合成的地址),创建成功返回插口ID(出错返回-1)。
参数:domain协议族(AF_UNIX是UNIX,AF_INET是IPv4协议,AF_ROUTE是路由器协议);type类型(SOCK_STREAM是TCP,SOCK_DGRAM是UDP,SOCK_RAW是RAM活IPv4);protocol为0。
该函数返回大于等于0的整数作为插口ID,如果出错返回-1
-------------------------------------------------------------------------------------
#include
int bind ( int sockFd, const struct sockaddr *sockAddr, int addrLen );
将插口名、本地端口号和本地IP地址绑定到指定插口上。一般在用作服务器时使用该函数。返回0成功,-1未成功。
参数:sockFd插口ID,由socket函数创建;sockAddr结构体包含插口地址信息,AF_UNIX用下面结构体
struct sockaddr {
unsigned short sa_family; // Address Family (domain)
char sa_data[14]]; // Protocol Address
};
AF_INET用下面的结构体,使用前需初始化,下面使用TCP函数时相同。
struct sockaddr_in {
short sin_family; // Address Family
unsigned short sin_port; // Port Number
struct in_addr sin_addr; // Internet Address
unsigned char sin_zero[8]; // Pad structure
};
addrLen是上述结构体长度。
-------------------------------------------------------------------------------------
#include
int listen ( int sockFd, int backlog );
TCP服务器监听指定插口
参数:sockFd已创建并被绑定的插口;backlog允许接收的客服端数量。
-------------------------------------------------------------------------------------
include
#include
int accept ( int sockFd, struct sockaddr *clientAddr, int *addrLen )
TCP服务器监听到连接时的响应函数。
参数:sockFd已创建、绑定并监听的插口;clientAddr远端连接信息;addrLen结构体长度。
-------------------------------------------------------------------------------------
#include
#include
int connect ( int sockFd, struct sockaddr *servAddr, int addrLen );
TCP/UDP客服端申请TCP/UDP服务器的链接。
参数:sockFd已创建的插口;servAddr服务器连接信息;addrLen结构体长度。
返回0成功,-1出错
-------------------------------------------------------------------------------------
#include
#include
#include
int select( int n, fd_set *read_fds, fd_set *write_fds,
fd_set *exceptfds, struct timeval *timeout );
挂起当前线程,等待特定事件发生或定时器过期。本函数可以指定4类特定事件:read、write、exception和超时。返回插口ID表示事件有响应,0表示超时,-1表示出错。
参数:n应该大于所有插口ID,用FD_SETSIZE代替;后面三个fd_set结构体存储三种插口事件位图:
typedef struct fd_set {
fd_mask fds_bits[(FD_SETSIZE + NFDBITS - 1) / NFDBITS];
} fd_set;
用以下四个宏修改:
FD_SET(fd, fdset) fd插口ID,fdset是fd_set结构体地址,设置插口事件为真
FD_CLR(fd, fdset)设置插口事件为假
FD_ISSET(fd, fdset)获取插口状态,是否设置
FD_ZERO(fdset)清除所有设置
第四个参数timeval结构体如下:
struct timeval {
int tv_sec; /* 秒 */
int tv_usec; /* 毫秒 */
};
用来设置超时时间。
-------------------------------------------------------------------------------------
#include
#include
int send ( int sockFd, const void *msg, int msgLen, unsigned int flags);
int sendto ( int sockFd, const void *msg, int msgLen, unsigned int flags,
const struct sockaddr *to, int toLen);
这两个函数都用来按插口发送数据包,send用在已经连接的插口,sendto用在没有连接上的插口。
send函数的参数:sockFD插口ID,msg要发送的数据指针,msgLen要发送的数据长度,flags发送选项(按位)
sendto函数的参数:UDP专用,插口必须是SOCK_DGRAM类型。由于没有连接,所以sendto函数增加了两个与连接有关的参数。to定义目标地址的结构体,toLen是结构体长度。sockaddr结构体如下:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
这两个函数返回值均为实际发送字节的长度(软件需要调整偏移量将数据全部发送),-1表示发送不成功。
-------------------------------------------------------------------------------------
#include
#include
int recv ( int sockFd, const void *msg, int msgLen, unsigned int flags);
int recvfrom ( int sockFd, const void *msg, int msgLen, unsigned int flags,
const struct sockaddr *from, int *fromLen);
这两个函数均是按插口来接收数据包,recv函数用在已连接插口上,recvfrom用在未连接插口上。
recv函数参数:sockFd插口ID,msg接收缓存地址,msgLen接收缓存最大空间,flags接收选项。
recvfrom函数参数:UDP专用,插口必须是SOCK_DRAM类型。由于没有连接,所以recvfrom函数增加了两个与连接有关的参数。from定义目标地址的结构体,formLen是结构体长度。
两个函数均返回接收到的数据数,-1接收错误,0表示目标地址已经传输完毕并关闭连接。
-------------------------------------------------------------------------------------
#include
#include
int setsockopt ( int sd, int level, int optname, const void *optval, socklen_t optlen);
int getsockopt ( int sd, int level, int optname, void *optval, socklen_t *optlen );
setsockopt函数用来改变插口的模式,这种改变是通过修改插口选项实现的。
getsockopt函数用来获取插口选项的值。
参数:sd插口ID;level协议栈选项,包括SOL_SOCKET(插口层)、IPPROTO_TCP(TCP层)和IPPROTO_IP(IP层);optname需要修改的选项名;optval修改值地址;optlen修改值长度。
返回0表示成功。
-------------------------------------------------------------------------------------
#include
int getsockname ( int sd, struct sockaddr *addr, int *addrLen );
int getpeername ( int sd, struct sockaddr *addr, int *addrLen );
getsockname函数用于从已连接的插口中获取本地地址信息。getpeername函数用于获取远端地址信息。
参数:sd插口ID;addr地址信息结构体;addrLen结构体长度。
返回0成功,-1错误
-------------------------------------------------------------------------------------
#include int close ( int sd );
关闭插口通信(丢弃未发送的数据包并拒绝接受数据)
-------------------------------------------------------------------------------------
#include
int shutdown ( int sockFd, int how );
该函数提供了更大的权限控制插口的关闭过程。
参数:sockFd插口ID;how仅能为0、1和2这三个值
0表示停止接收当前数据并拒绝以后的数据接收
1表示停驶发送数据并丢弃未发送的数据
2是0和1的合集
-------------------------------------------------------------------------------------
int read (int sockFD, void *buffer, UInt32 numBytes);
从指定插口中等待数据接收并存放到buffer中。该函数会挂起线程,直到有数据接收到。
参数:sockFd插口ID;buffer缓存地址;numBytes缓冲大小
该函数返回接收到的数据大小,-1表示出错,0表示远端已经关闭连接。
-------------------------------------------------------------------------------------
int write (int sockFD, void *buffer, UInt32 numBytes);
将缓存中数据写到指定插口准备发送。
参数:sockFd插口ID;buffer缓存地址;numBytes缓存中数据大小
该函数返回实际发送的数据量,-1表示出错。
-------------------------------------------------------------------------------------
补充:
lwIP协议栈在socket模式下也就是操作系统中运行,创建进程的方式与操作系统中创建进程的方式有所不同。要用专用函数:
sys_thread_t sys_thread_new(char *name, void(* thread)(void *arg), void *arg, int stacksize, int prio)
参数:name线程说明;thread线程函数;arg线程函数的参数;stacksize线程堆栈大小;prio线程优先级
在lwIP下创建线程统一使用此函数,当然这个函数也是要调用系统创建线程的API的。