1.select poll epol(lt模式)下socket什么时候就绪
缓冲区的字节数 >= SO_RECVLOWAT的时候
如果一次没有读完缓冲区,则下一次还是会触发select, poll, epoll的!!
2.举例说明
client.cpp
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
const char* ip = "0.0.0.0";
int port = 2345;
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &(addr.sin_addr));
int fd = socket(AF_INET, SOCK_STREAM, 0);
assert(fd >= 0);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
cout << "failed" << endl;
const char* data = "0123456789";
char buffer[1024];
// memset(buffer, '\0', sizeof(buffer));
send(fd, data, strlen(data), 0);
// recv(fd, buffer, sizeof(buffer), 0);
//cout << buffer << endl;
close(fd);
return 0;
}
server.cpp
#include<iostream>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<string.h>
#include <signal.h>
#include <sys/select.h>
using namespace std;
#define BUF_SIZE 6
static bool run = true;
static void handle_term(int sig)
{
run = false;
}
int main()
{
signal(SIGTERM, handle_term);
const char* ip = "0.0.0.0";
int port = 2345;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int sock = socket(AF_INET, SOCK_STREAM, 0);
assert(sock > 0);
int ret = bind(sock, (struct sockaddr* )&address, sizeof(address));
assert(ret != -1);
ret = listen(sock, 5);
assert(ret != -1);
struct sockaddr_in client;
socklen_t len1 = sizeof(client);
int connfd = accept(sock, (struct sockaddr*)&address, &len1);
if (connfd < 0) cout << "err" << endl;
else
{
fd_set read_fds;
fd_set exc_fds;
FD_ZERO(&read_fds);
FD_ZERO(&exc_fds);
char buffer[BUF_SIZE];
while (run)
{
memset(buffer, '\0', sizeof(buffer));
FD_SET(connfd, &read_fds);
FD_SET(connfd, &exc_fds);
ret = select(connfd+1, &read_fds, NULL, &exc_fds, NULL);
if (ret < 0)
{
cout << "select failed" << endl;
break;
}
if (FD_ISSET(connfd, &read_fds))
{
ret = recv(connfd, buffer, sizeof(buffer)-1, 0);
if (ret <= 0) break;
cout << buffer << endl;
}
else if (FD_ISSET(connfd, &exc_fds))
{
ret = recv(connfd, buffer, sizeof(buffer)-1, MSG_OOB);
if (ret <= 0) break;
cout << buffer << endl;
}
}
}
close(connfd);
close(sock);
return 0;
}
注意,
ret = recv(connfd, buffer, sizeof(buffer)-1, 0);
从socket缓冲区读取sizeof(buffer)-1个字节到buffer里面,buffer后面的都是\0
可以把上面这行换成
if (FD_ISSET(connfd, &read_fds))
{
ret = recv(connfd, buffer, sizeof(buffer)-2, 0);
if (ret <= 0) break;
cout << "ret is " << ret << endl;
cout << buffer << endl;
}
打印buffer[sizeof(buffer)-1],得到
ret is 4
0123
ret is 4
4567
ret is 2
89
每次最多读4个,4个字符之后的都是\0