基本TCP套接字
更加详细的信息请参考《Unix网络编程 卷1:套接字联网API》,里面详细列举出返回某种状态码时对应何种情况和其他更加详细的介绍。
TCP套接字建立过程需要服务器端按照 socket() -> bind() -> listen() -> accept() 然后等待客户端的连接请求,客户端需要 socket() -> connect() 来连接服务器。 连接成功两者通过write() read() 来进行交互。最后两者通过close() 来结束本次连接
int socket(int family, int type, int protocol) 返回:若成功则为非负描述符,若出错则为-1 family,AF_INET 是IPv4协议,AF_INET6是IPv6协议;type,SOCK_STREAM是字节流套接字(TCP/IP) SOCK_DGRAM是数据包套接字(UDP) SOCK_RAW是原始套接字;protocol,IPPROTO_TCP是TCP传输协议 IPPROTO_UDP是UDP传输协议。
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen) 返回:若成功则为0,若出错则为-1 sockfd是客户端socket函数返回的套接字描述符
int bind(sockfd, const struct sockaddr *myaddr, socklen_t addrlen) 返回:若成功则为0,若出错则为-1 sockfd是服务器端socket函数返回的套接字描述符
int listen(int sockfd, int backlog) 返回:若成功则为0,若出错则为-1
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
基本UDP套接字
UDP是不安全的非连接的网络层协议。UDP服务器通过 socket() -> bind() - > recvfrom() 一直等待客户端的数据请求。 UDP客户端通过socket() -> sendto() 然后和服务器端进行数据交换。
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, sturct sockaddr *from, socklen_t addrlen) 返回:若成功则为读或写的字节数,若出错则为-1
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen) 返回:若成功则为读或写的字节数,若出错则为-1
其他函数
int getsockopt(int sockfd, intlevel, int optname, void *optval, socklen_t *optlen) 返回:0--成功,-1--出错
int setsockopt(int sockfd, intlevel, int optname, void *optval, socklen_t *optlen) 返回:0--成功,-1--出错
在Windows Socket API中对应如下:
读取socket属性:
int getsockopt(SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)
s为欲读取属性的套接字。level为套接字选项的级别,大多数是特定协议和套接字专有的。如IP协议应为 IPPROTO_IP。
optname为读取选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=0; //读取TTL值
int rc = getsockop( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));
设置socket属性:
int setsockopt(SOCKET s,int level, int optname,const char FAR * optval, int optlen)
s为欲设置属性的套接字。
level为套接字选项的级别,用法同上。
optname为设置选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=32; //设置TTL值
int rc = setsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));
以下这段 摘自百度百科:http://baike.baidu.com/view/569217.htm
setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。
有两种套接口的选项:一种是布尔型选项,允许或禁止一种特性;另一种是整形或结构选项。允许一个布尔型选项,则将optval指向非零整形数;禁止一个选项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其他选项,optval指向包含所需选项的整形数或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,且closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。
TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。
*******************************************************************************
SO_BROADCAST BOOL 允许套接口传送广播信息。
SO_DEBUG BOOL 记录调试信息。
SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。
SO_DONTROUTE BOOL 禁止选径;直接传送。
SO_KEEPALIVE BOOL 发送“保持活动”包。
SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。
SO_OOBINLINE BOOL 在常规数据流中接收带外数据。
SO_RCVBUF int 为接收确定缓冲区大小。
SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。
SO_SNDBUF int 指定发送缓冲区大小。
TCP_NODELAY BOOL 禁止发送合并的Nagle算法。
setsockopt()不支持的BSD选项有:
选项名 类型 意义
SO_ACCEPTCONN BOOL 套接口在监听。
SO_ERROR int 获取错误状态并清除。
SO_RCVLOWAT int 接收低级水印。
SO_RCVTIMEO int 接收超时。
SO_SNDLOWAT int 发送低级水印。
SO_SNDTIMEO int 发送超时。
SO_TYPE int 套接口类型。
IP_OPTIONS 在IP头中设置选项。
u_long htonl(u_long hostlong) 将u_long类型的主机字节顺序格式的IP地址转换为TCP/IP网络字节顺序格式
u_short htons(u_short hostshort) 将u_short类型的主机字节顺序格式的IP地址转换为TCP/IP网络字节顺序格式
u_long ntohl(u_long netlong) 将TCP/IP网络字节顺序格式转换为u_long类型的主机字节顺序格式的IP地址
u_short ntohs(u_short netshort) 将TCP/IP网络字节顺序格式转换为u_short类型的主机字节顺序格式的IP地址
unsigned long inet_addr( const char FAR * cp ); 将用点分割的IP地址转换位一个in_addr结构的地址,这个结构的定义见笔记(一),实际上就是一个unsigned long值。计算机内部处理IP地址可是不认识如192.1.8.84之类的数据。 举例:inet_addr("192.1.8.84")=1409810880; inet_addr("127.0.0.1")= 16777343
char FAR * inet_ntoa( struct in_addr in ); char * ipaddr=NULL; char addr[20]; in_addr inaddr; inaddr. s_addr=16777343; ipaddr= inet_ntoa(inaddr); strcpy(addr,ipaddr);
int WSAGetLastError(void ) 读取当前错误值:每次发生错误时,如果要对具体问题进行处理,那么就应该调用这个函数取得错误代码。
int getsockname(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ); 获取套接字的本地地址结构:s为套接字,name为函数调用后获得的地址值,namelen为缓冲区的大小。
int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ) 获取与套接字相连的端地址结构:s为套接字,name为函数调用后获得的端地址值,namelen为缓冲区的大小。
int gethostname( char FAR * name, int namelen ) 获取计算机名:name是存放计算机名的缓冲区,namelen是缓冲区的大小。用法: char szName[255]; memset(szName,0,255); if(gethostname(szName,255)==SOCKET_ERROR) { //错误处理 } 返回值为:szNmae="xiaojin"
struct hostent FAR * gethostbyname( const char FAR * name ); 根据计算机名获取主机地址。name为计算机名。 用法: hostent * host; char* ip; host= gethostbyname("xiaojin"); if(host->h_addr_list[0]) { struct in_addr addr; memmove(&addr, host->h_addr_list[0],4); //获得标准IP地址 ip=inet_ ntoa (addr); } 返回值为:hostent->h_name="xiaojin" hostent->h_addrtype=2 //AF_INET hostent->length=4 ip="127.0.0.1"
int closesocket(SOCKET s) 关闭socket
int shutdown(SOCKET s, int how) 不允许进行某些操作(包括读、写、读写等)