12.套接口选项:套接口低潮限度
之前曾经提到过这个名词,套接口低潮限度。(以下都只针对TCP)
?
接收低潮限度(SO_RCVLOWAT):之前我们曾经使用过select函数,如果将套接口可读,也就是说套接口中有数据可以读出做为select的一个阻塞条件,则什么叫做有数据可读?其实就是指套接口中数据大小大于低潮限度。默认的低潮大小为1,也就是只要有数据到达就表示可读。
?
发送低潮限度(SO_SNDLOWAT):和上面一样,就是当你想对某个套接口执行write时候,如果空闲大小大于等于低潮限度就表示可写,也就是会从select函数返回。比如说下面的程序
#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/wait.h"
#include "sys/select.h"
#include "sys/time.h"
#define MAXSIZE 100
#define LISTENQ 10
int main(int argc, char ** argv) {
??????? int listenfd, connfd;
??????? socklen_t client_len;
??????? struct sockaddr_in client_socket, serv_socket;
??????? char send[MAXSIZE + 1], recv[MAXSIZE + 1];
??????? listenfd = socket(AF_INET, SOCK_STREAM, 0);
??????? bzero(&serv_socket, sizeof(serv_socket));
??????? serv_socket.sin_family = AF_INET;
??????? serv_socket.sin_addr.s_addr = htonl(INADDR_ANY);
??????? serv_socket.sin_port = htons(atoi(argv[1]));
??????? bind(listenfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));
??????? listen(listenfd, LISTENQ);
??????? client_len = sizeof(client_socket);
??????? connfd = accept(listenfd, (struct sockaddr *)&client_socket, &client_len);
??????? int recv_min_size = 6;
??????? int flag = setsockopt(connfd, SOL_SOCKET, SO_RCVLOWAT, (void *)&recv_min_size, sizeof(int));
??????? //设置接受低潮
??????? int recv_min_size1;
??????? socklen_t recv_min_len = sizeof(recv_min_size1);
??????? getsockopt(connfd, SOL_SOCKET, SO_RCVLOWAT, (void *)&recv_min_size1, &recv_min_len);
??????? if(flag >= 0)
??????????????? printf("set SO_RCVLOWAT OK!!! SO_RCVLOWAT = %d\n", recv_min_size1);
??????? else
??????????????? printf("set SO_RCVLOWAT failed!!! SO_RCVLOWAT = %d\n", recv_min_size1);
??????? for(;;) {
??????????????? fd_set rest;
??????????????? FD_ZERO(&rest);
??????????????? FD_SET(1, &rest);
??????????????? FD_SET(connfd, &rest);
??????????????? int maxfdpl = 2;
??????????????? if(maxfdpl < connfd + 1)
??????????????????????? maxfdpl = connfd + 1;
??????????????? int flag = select(maxfdpl, &rest, NULL, NULL, NULL); //? 2
??????????????? if(flag <= 0) {
??????????????????????? printf("some error happend, sorry");
??????????????? } else {
??????????????????????? if(FD_ISSET(1, &rest)) {
??????????????????????????????? int n = read(1, send, MAXSIZE);
??????????????????????????????? send[n] = '\0';
??????????????????????????????? write(connfd, send, n);
??????????????????????? }
??????????????????????? if(FD_ISSET(connfd, &rest)) {
??????????????????????????????? int n = read(connfd, recv, MAXSIZE);
??????????????????????????????? if(n == 0) {
??????????????????????????????????????? printf("client closed\n");
??????????????????????????????????????? break;
??????????????????????????????? }
??????????????????????????????? recv[n] = '\0';
??????????????????????????????? printf("get message:%s", recv);
??????????????????????? }
??????????????? }
??????? }
}
和之前的代码没有什么不同,只是增加了设置接受低潮。下面是客户端代码:
#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/select.h"
#define MAXSIZE 100
int main(int argc, char ** argv) {
??????? int sockfd;
??????? struct sockaddr_in serv_socket;
??????? int maxfdpl;
??????? char send[MAXSIZE], recv[MAXSIZE];
??????? if(argc != 2) {
??????????????? printf("please input port");
??????????????? exit(1);
??????? }
??????? sockfd = socket(AF_INET, SOCK_STREAM, 0);
??????? bzero(&serv_socket, sizeof(serv_socket));
??????? serv_socket.sin_family = AF_INET;
??????? serv_socket.sin_port = htons(atoi(argv[1]));
??????? inet_pton(AF_INET, "192.168.1.235", &serv_socket.sin_addr);
??????? connect(sockfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));
??????? for(;;) {
??????????????? fd_set rset;
??????????????? FD_ZERO(&rset);
??????????????? FD_SET(1, &rset);
??????????????? FD_SET(sockfd, &rset);
??????????????? maxfdpl = sockfd + 1;
??????????????? select(maxfdpl, &rset, NULL, NULL, NULL); //? 1
??????????????? if(FD_ISSET(sockfd, &rset)) {
??????????????????????? int n = read(sockfd, recv, MAXSIZE);
??????????????????????? if(!n) {
??????????????????????????????? printf("server closed\n");
??????????????????????????????? break;
??????????????????????? }
??????????????????????? recv[n] = '\0';
??????????????????????? printf("get message from server:%s\n", recv);
??????????????? }
??????????????? if(FD_ISSET(1, &rset)) {
??????????????????????? int n = read(1, send, MAXSIZE);
??????????????????????? send[n] = '\0';
??????????????????????? write(sockfd, send, n);
??????????????? }
??????? }
??????? close(sockfd);
??????? exit(0);
}
运行就会发现如果你输入的字符个数少于6(包括回车),select会继续阻塞。(注:我测试了一下,低潮限度只是会对select造成影响,不会对read和write函数的阻塞造成影响)