简体   繁体   English

这个插座 select 代码有什么问题?

[英]What`s wrong with this socket select code?

#include <stdio.h>
#include <time.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "WS2_32.lib")

#define IP_ADDRESS "127.0.0.1"
#define PORT        20000
#define BUF_SIZE    64

#undef FD_SETSIZE
#define FD_SETSIZE 10000

void shuffle_buffer(char* buf, size_t size);
SOCKET create_socket();
void send_data(SOCKET sock);

int main()
{
    WSADATA  ws;

    if (WSAStartup(MAKEWORD(2, 2), &ws) != 0)
    {
        printf("Init Windows Socket Failed::%d\n", GetLastError());
        return -1;
    }

    const int CLIENT_SIZE = 1;
    SOCKET socks[CLIENT_SIZE];
    struct timeval tv = { 0, 10 };
    fd_set fd_read, fd_write;
    FD_ZERO(&fd_read);
    FD_ZERO(&fd_write);

    for (int i = 0; i < CLIENT_SIZE; i++) {
        SOCKET sock = create_socket();
        socks[i] = sock;
        FD_SET(sock, &fd_write);
        FD_SET(sock, &fd_read);
    }

    Sleep(1000);

    int number_to_recv = CLIENT_SIZE;
    while (number_to_recv > 0) {
        int ret = select(CLIENT_SIZE, &fd_read, &fd_write, NULL, &tv);
        for (int i = 0; i < CLIENT_SIZE; i++) {
            if (FD_ISSET(socks[i], &fd_read)) {
                char buf[BUF_SIZE];
                int n = recv(socks[i], buf, BUF_SIZE, 0);
                buf[n] = 0;
                printf("%s\n", buf);
                number_to_recv--;
            }

            if (FD_ISSET(socks[i], &fd_write)) {
                send_data(socks[i]);
                FD_CLR(socks[i], &fd_write);
                //Sleep(1);
            }
        }
        //printf("ret and number : %d, %d\n", ret, number_to_recv);
    }

    for (int i = 0; i < CLIENT_SIZE; i++) {
        closesocket(socks[i]);
    }
    WSACleanup();
}

SOCKET create_socket() 
{
    SOCKET cli_sock;
    struct sockaddr_in addr;

    if ((cli_sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
        printf("Create Socket Failed::%d\n", GetLastError());
        return -1;
    }
    //inet_pton
    memset(addr.sin_zero, 0x00, 8);
    addr.sin_family = AF_INET;
    inet_pton(AF_INET, IP_ADDRESS, (void*)(&addr.sin_addr.s_addr));
    addr.sin_port = htons(PORT);

    if (connect(cli_sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        printf("Connect Error::%d\n", GetLastError());
        return -1;
    }

    return cli_sock;
}

void send_data(SOCKET sock)
{
    const int SEND_SIZE = BUF_SIZE / 2;
    char buf[SEND_SIZE] = { 0 };
    memset(buf, 'a', SEND_SIZE);
    shuffle_buffer(buf, SEND_SIZE);

    if (send(sock, buf, SEND_SIZE, 0) == SOCKET_ERROR)
    {
        printf("Send Info Error::%d\n", GetLastError());
    }
}

void shuffle_buffer(char* buf, size_t size)
{
    for (int i = 0; i < size; i++) {
        buf[i] += int(rand() % 26);
    }
}

Code above is a socket client using select model run on Win10, the problem is after I send data, but I can not receive data(I am sure that server has sent back data), this code below doesn`t run, so what is the problem?上面的代码是一个socket客户端使用select model在Win10上运行,问题是我发送数据后,但我无法接收数据(我确定服务器已经发回数据),下面这段代码没有运行,那是什么问题? Thanks谢谢

The first parameter in select is maxfdp , and I know the difference between Win and Unix, so on Windows, this parameter seems not necessary, and I can write data, but can not receive it. maxfdp select我知道Win和Unix的区别,所以Windows,这个参数好像没必要,而且我不能接收数据,

if (FD_ISSET(socks[i], &fd_read)) {
    char buf[BUF_SIZE];
    int n = recv(socks[i], buf, BUF_SIZE, 0);
    buf[n] = 0;
    printf("%s\n", buf);
    number_to_recv--;
}

select removes the sockets from the fd_set if they are not readable/writable. select如果 sockets 不可读/可写,则从fd_set中删除它们。 You need to add them back in before the next time you call select .您需要在下次调用select之前重新添加它们。

The reason your code can write data is because sockets start out being writable, so they will still be set in fd_write and your code will write data.您的代码可以写入数据的原因是因为 sockets 开始是可写的,因此它们仍将在fd_write中设置,您的代码将写入数据。 They don't start out being readable, if no data has been received yet, so they'll be removed from the fd_read set and then your code stops checking whether they are readable.如果尚未收到数据,它们一开始是不可读的,因此它们将从fd_read集中删除,然后您的代码将停止检查它们是否可读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM