http://home.eeworld.com.cn/my/space-uid-162102-blogid-52270.html
2011
原文:
關于BSD Socket API
在網(wǎng)上找到的兩個網(wǎng)站,是關于BSD Sockets API的,這是與lwIP在Socket模式下兼容的。里面對API函數(shù)做了較為詳細的介紹,先記下來,有空翻譯一下
http://web.mit.edu/macdev/Development/MITSupportLib/SocketsLib/Documentation/sockets.html
http://book.opensourceproject.org.cn/embedded/tcpipembedded/index.html?page=opensource/0107.html
-------------------------------------------------------------------------------------
最常用的BSD API函數(shù):
socket:創(chuàng)建一個插口(socket)
bind:將本地端口號和IP地址綁定到插口上
listen:TCP監(jiān)聽
accept:TCP監(jiān)聽接受處理
connect:TCP客戶端連接
select:特殊插口設置
send/sendto:發(fā)送數(shù)據(jù)包到已連接/未連接插口上
recv/recvfrom:接收數(shù)據(jù)包從已連接/未連接插口上
getsockopt/setsockopt:獲取/改變插口選項
getpeername/getsockname:獲取遠端/本地地址信息
close:關閉插口
shutdown:按設置關閉插口
gethostbyname/gethostbyaddr:地址域名映射
read:從插口緩存讀數(shù)據(jù)
write:想插口緩存寫數(shù)據(jù)
-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
int socket( int domain, int type, int protocol );
創(chuàng)建通訊用的“插口”(插口socket可以理解為IP地址和端口號組合成的地址),創(chuàng)建成功返回插口ID(出錯返回-1)。
參數(shù):domain協(xié)議族(AF_UNIX是UNIX,AF_INET是IPv4協(xié)議,AF_ROUTE是路由器協(xié)議);type類型(SOCK_STREAM是TCP,SOCK_DGRAM是UDP,SOCK_RAW是RAM活IPv4);protocol為0。
該函數(shù)返回大于等于0的整數(shù)作為插口ID,如果出錯返回-1
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
int bind ( int sockFd, const struct sockaddr *sockAddr, int addrLen );
將插口名、本地端口號和本地IP地址綁定到指定插口上。一般在用作服務器時使用該函數(shù)。返回0成功,-1未成功。
參數(shù):sockFd插口ID,由socket函數(shù)創(chuàng)建;sockAddr結構體包含插口地址信息,AF_UNIX用下面結構體
struct sockaddr {
unsigned short sa_family; // Address Family (domain)
char sa_data[14]]; // Protocol Address
};
AF_INET用下面的結構體,使用前需初始化,下面使用TCP函數(shù)時相同。
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 <sys/socket.h>
int listen ( int sockFd, int backlog );
TCP服務器監(jiān)聽指定插口
參數(shù):sockFd已創(chuàng)建并被綁定的插口;backlog允許接收的客服端數(shù)量。
-------------------------------------------------------------------------------------
include <sys/types.h>
#include <sys/socket.h>
int accept ( int sockFd, struct sockaddr *clientAddr, int *addrLen )
TCP服務器監(jiān)聽到連接時的響應函數(shù)。
參數(shù):sockFd已創(chuàng)建、綁定并監(jiān)聽的插口;clientAddr遠端連接信息;addrLen結構體長度。
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
int connect ( int sockFd, struct sockaddr *servAddr, int addrLen );
TCP/UDP客服端申請TCP/UDP服務器的鏈接。
參數(shù):sockFd已創(chuàng)建的插口;servAddr服務器連接信息;addrLen結構體長度。
返回0成功,-1出錯
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
int select( int n, fd_set *read_fds, fd_set *write_fds,
fd_set *exceptfds, struct timeval *timeout );
掛起當前線程,等待特定事件發(fā)生或定時器過期。本函數(shù)可以指定4類特定事件:read、write、exception和超時。返回插口ID表示事件有響應,0表示超時,-1表示出錯。
參數(shù):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)獲取插口狀態(tài),是否設置
FD_ZERO(fdset)清除所有設置
第四個參數(shù)timeval結構體如下:
struct timeval {
int tv_sec; /* 秒 */
int tv_usec; /* 毫秒 */
};
用來設置超時時間。
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
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);
這兩個函數(shù)都用來按插口發(fā)送數(shù)據(jù)包,send用在已經(jīng)連接的插口,sendto用在沒有連接上的插口。
send函數(shù)的參數(shù):sockFD插口ID,msg要發(fā)送的數(shù)據(jù)指針,msgLen要發(fā)送的數(shù)據(jù)長度,flags發(fā)送選項(按位)
sendto函數(shù)的參數(shù):UDP專用,插口必須是SOCK_DGRAM類型。由于沒有連接,所以sendto函數(shù)增加了兩個與連接有關的參數(shù)。to定義目標地址的結構體,toLen是結構體長度。sockaddr結構體如下:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
這兩個函數(shù)返回值均為實際發(fā)送字節(jié)的長度(軟件需要調(diào)整偏移量將數(shù)據(jù)全部發(fā)送),-1表示發(fā)送不成功。
-------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
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);
這兩個函數(shù)均是按插口來接收數(shù)據(jù)包,recv函數(shù)用在已連接插口上,recvfrom用在未連接插口上。
recv函數(shù)參數(shù):sockFd插口ID,msg接收緩存地址,msgLen接收緩存最大空間,flags接收選項。
recvfrom函數(shù)參數(shù):UDP專用,插口必須是SOCK_DRAM類型。由于沒有連接,所以recvfrom函數(shù)增加了兩個與連接有關的參數(shù)。from定義目標地址的結構體,formLen是結構體長度。
兩個函數(shù)均返回接收到的數(shù)據(jù)數(shù),-1接收錯誤,0表示目標地址已經(jīng)傳輸完畢并關閉連接。
-------------------------------------------------------------------------------------
#include <sys/types.h>#include <sys/socket.h>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函數(shù)用來改變插口的模式,這種改變是通過修改插口選項實現(xiàn)的。
getsockopt函數(shù)用來獲取插口選項的值。
參數(shù):sd插口ID;level協(xié)議棧選項,包括SOL_SOCKET(插口層)、IPPROTO_TCP(TCP層)和IPPROTO_IP(IP層);optname需要修改的選項名;optval修改值地址;optlen修改值長度。
返回0表示成功。
-------------------------------------------------------------------------------------
#include <sys/socket.h>
int getsockname ( int sd, struct sockaddr *addr, int *addrLen );
int getpeername ( int sd, struct sockaddr *addr, int *addrLen );
getsockname函數(shù)用于從已連接的插口中獲取本地地址信息。getpeername函數(shù)用于獲取遠端地址信息。
參數(shù):sd插口ID;addr地址信息結構體;addrLen結構體長度。
返回0成功,-1錯誤
-------------------------------------------------------------------------------------
#include <sys/socket.h> int close ( int sd );
關閉插口通信(丟棄未發(fā)送的數(shù)據(jù)包并拒絕接受數(shù)據(jù))
-------------------------------------------------------------------------------------
#include <sys/socket.h>
int shutdown ( int sockFd, int how );
該函數(shù)提供了更大的權限控制插口的關閉過程。
參數(shù):sockFd插口ID;how僅能為0、1和2這三個值
0表示停止接收當前數(shù)據(jù)并拒絕以后的數(shù)據(jù)接收
1表示停駛發(fā)送數(shù)據(jù)并丟棄未發(fā)送的數(shù)據(jù)
2是0和1的合集
-------------------------------------------------------------------------------------
int read (int sockFD, void *buffer, UInt32 numBytes);
從指定插口中等待數(shù)據(jù)接收并存放到buffer中。該函數(shù)會掛起線程,直到有數(shù)據(jù)接收到。
參數(shù):sockFd插口ID;buffer緩存地址;numBytes緩沖大小
該函數(shù)返回接收到的數(shù)據(jù)大小,-1表示出錯,0表示遠端已經(jīng)關閉連接。
-------------------------------------------------------------------------------------
int write (int sockFD, void *buffer, UInt32 numBytes);
將緩存中數(shù)據(jù)寫到指定插口準備發(fā)送。
參數(shù):sockFd插口ID;buffer緩存地址;numBytes緩存中數(shù)據(jù)大小
該函數(shù)返回實際發(fā)送的數(shù)據(jù)量,-1表示出錯。
-------------------------------------------------------------------------------------
補充:
lwIP協(xié)議棧在socket模式下也就是操作系統(tǒng)中運行,創(chuàng)建進程的方式與操作系統(tǒng)中創(chuàng)建進程的方式有所不同。要用專用函數(shù):
sys_thread_t sys_thread_new(char *name, void(* thread)(void *arg), void *arg, int stacksize, int prio)
參數(shù):name線程說明;thread線程函數(shù);arg線程函數(shù)的參數(shù);stacksize線程堆棧大??;prio線程優(yōu)先級
在lwIP下創(chuàng)建線程統(tǒng)一使用此函數(shù),當然這個函數(shù)也是要調(diào)用系統(tǒng)創(chuàng)建線程的API的。