第七章 套接字选项:
#include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void * optval, socklen_t * optlen); int setsockopt(int sockfd, int level, int optname, const void * optval, socklen_t optlen); success return 0, error return -1 level = SOL_SOCKET: optname: SO_DEBUG, only for TCP SO_DONTROUTE, SO_KEEPALIVE, send check seg per 2hours, may get error: ECONNRESET/ETIMEDOUT/EHOSTUNREACH SO_LINGER, struct linger { int l_onoff; /* 0=off, nonzero=on */ int l_linger; /* linger time, as seconds */ }; l_onoff is 0: close() no wait to return l_onoff is nonzero and l_linger is 0: close() send RST, no four-connect-stop-orders, no TIME_WAIT state l_onoff is nonzero and l_linger is nonzero: if time out close() return EWOULDBLOCK SO_OOBINLINE, SO_RCVBUF, SO_RCVLOWAT, SO_SNDBUF, SO_SNDLOWAT, SO_RCVTIMEO, SO_SNDTIMEO, SO_REUSEADDR, TCP-server should set this socket option SO_REUSEPORT, SO_TYPE, level = IPPROTO_TCP: optname: TCP_MAXSEG, TCP_NODELAY, forbid TCP-Nagle algorithm (default) int bind_connect_listen(int sockfd, const struct sockaddr * laddr, int laddrlen, const struct sockaddr * faddr, int faddrlen, int listen); better than bind() + (connect()/listen()) success return 0, error return -1 #include <fcntl.h> int fcntl(int fd, int cmd, ... /* int arg */ ); cmd: GETFL, SETFL, GETOWN, SETOWN error return -1 cmd = F_SETFL, arg = O_NONBLOCK cmd = F_SETFL, arg = O_ASYNC, get SIGIO when io-done
示例:
#include <stdio.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/socket.h> #include <netinet/tcp.h> int main(int argc, char * argv[]) { int sockfd; int rcvbuf; int mss; socklen_t len; struct sockaddr_in servaddr; if (argc != 2) { printf("usage: rcvbuf <IPaddress>\n"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("socket error: %s\n", strerror(errno)); exit(1); } len = sizeof(rcvbuf); if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len) == -1) { printf("getsockopt SO_RCVBUF error: %s\n", strerror(errno)); exit(1); } len = sizeof(mss); if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len) == -1) { printf("getsockopt TCP_MAXSEG error: %s\n", strerror(errno)); exit(1); } printf("defaults: SO_RCVBUF = %d, MSS = %d\n", rcvbuf, mss); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(13); /* daytime server */ if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { printf("inet_pton error: %s\n", strerror(errno)); exit(1); } if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { printf("connect error: %s\n", strerror(errno)); exit(1); } len = sizeof(rcvbuf); if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len) == -1) { printf("getsockopt SO_RCVBUF error: %s\n", strerror(errno)); exit(1); } len = sizeof(mss); if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len) == -1) { printf("getsockopt TCP_MAXSEG error: %s\n", strerror(errno)); exit(1); } printf("after connect: SO_RCVBUF = %d, MSS = %d\n", rcvbuf, mss); exit(0); }