socket的緩衝區

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章