#include <sys/socket.h>
int getsockopt(int socket, int level, int option_name,
void *restrict option_value, socklen_t *restrict option_len);
功能:获取套接字相关的选项信息
参数:
socket: 文件描述符
level: 对应协议层
SOL_SOCKET 应用层
IPPROTO_TCP TCP层
IPPROTO_IP IP层
option_name:选项的名称
SO_BROADCAST 允许发送广播 int
SO_REUSEADDR 允许重复使用地址 int
SO_SNDBUF 获取发送缓冲器大小
SO_RCVBUF 获取接收缓冲区大小
SO_RCVTIMEO 设置接收超时时间
SO_SNDTIMEO 设置发送超时时间
option_value:对应选项的值
option_len:大小
返回值:
成功:0
失败:-1码片
让我们用 select() 函数实现的并发服务来做实验吧
运行服务器、客户端后,服务器的现象是recv size = 85k, send size = 16k;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#define errmes(mes) do{perror(mes);exit(1);}while(0)
#define N 128
int main(int argc, const char *argv[])
{
int sockfd, acceptfd, maxfd;
struct sockaddr_in serveraddr, clientaddr;
char buf[N] = {};
fd_set readfds, tempfds;
socklen_t clientlen = sizeof(clientaddr);
int i = 0;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
errmes("fail to socket");
}
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
if(bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
{
errmes("fail to bind");
}
if(listen(sockfd, 10) < 0)
{
errmes("fail to listen");
}
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
maxfd = sockfd;
while(1)
{
tempfds = readfds;
if(select(maxfd+1, &tempfds, NULL, NULL, NULL) < 0)
{
errmes("fail to select");
}
for(i = 0; i < maxfd+1; i++)
{
if(FD_ISSET(i, &tempfds) == 1)
{
if(i == sockfd)
{
if((acceptfd = accept(sockfd, (struct sockaddr*)&clientaddr, &clientlen)) < 0)
{
errmes("fail to accept");
}
int bufsize;
socklen_t size = sizeof(bufsize);
if(getsockopt(acceptfd, SOL_SOCKET, SO_RCVBUF, &bufsize, &size) < 0)
{
errmes("fail to getsockopt");
}
printf("recv size = %d\n",bufsize/1024);
if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &bufsize, &size) < 0)
{
errmes("fail to getsockopt");
}
printf("send size =%d\n",bufsize/1024);
FD_SET(acceptfd, &readfds);
maxfd = maxfd > acceptfd ? maxfd : acceptfd ;
printf("%s---->%d\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
}
else
{
if(recv(i, buf, N, 0) < 0)
{
errmes("fail to recv");
}
if(strncmp(buf, "quit", 4) == 0)
{
printf("%s---quit\n",inet_ntoa(clientaddr.sin_addr));
return 0;
}
else
{
printf("%s\n",buf);
strcat(buf, "来自服务器");
if(send(i, buf, N, 0) < 0)
{
errmes("fail to send");
}
}
}
}
}
}
close(sockfd);
close(acceptfd);
return 0;
}