第七章 套接字选项:
#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);
}