BSD套接字 - 如何使用非阻塞套接字? [英] BSD Sockets - How to use non-blocking sockets?

查看:205
本文介绍了BSD套接字 - 如何使用非阻塞套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用非阻塞TCP套接字。问题是他们仍然阻塞。代码如下 -

I am trying to use non-blocking TCP sockets. The problem is that they are still blocking. The code is below -

服务器代码 -

struct sockaddr name;
char buf[80];

void set_nonblock(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}

int main(int agrc, char** argv) {

    int sock, new_sd, adrlen;   //sock is this socket, new_sd is connection socket

    name.sa_family = AF_UNIX;
    strcpy(name.sa_data, "127.0.0.1");
    adrlen = strlen(name.sa_data) + sizeof(name.sa_family);

    //make socket
    sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if (sock < 0) {
        printf("\nBind error %m", errno);
        exit(1);
    }

    //unlink and bind
    unlink("127.0.0.1");
    if(bind (sock, &name, adrlen) < 0)
        printf("\nBind error %m", errno);

    //listen
    if(listen(sock, 5) < 0)
        printf("\nListen error %m", errno);

    //accept
    new_sd = accept(sock, &name, (socklen_t*)&adrlen);
    if( new_sd < 0) {
        cout<<"\nserver accept failure "<<errno;
        exit(1);
    }

    //set nonblock
    set_nonblock(new_sd);

    char* in = new char[80];
    std::string out = "Got it";
    int numSent;
    int numRead;

    while( !(in[0] == 'q' && in[1] == 'u' && in[2] == 'i' && in[3] == 't') ) {

        //clear in buffer
        for(int i=0;i<80;i++)
            in[i] = ' ';

        cin>>out;
        cin.get();

        //if we typed something, send it
        if(strlen(out.c_str()) > 0) {
            numSent = send(new_sd, out.c_str(), strlen(out.c_str()), 0);
            cout<<"\n"<<numSent<<" bytes sent";
        }

        numRead = recv(new_sd, in, 80, 0);
        if(numRead > 0)
            cout<<"\nData read from client - "<<in;

     }   //end while

     cout<<"\nExiting normally\n";
     return 0;
}

客户端代码 -

struct sockaddr name;

void set_nonblock(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}

int main(int agrc, char** argv) {

    int sock, new_sd, adrlen;

    sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if (sock < 0) {
        printf("\nserver socket failure %m", errno);
        exit(1);
    }

    //stuff for server socket
    name.sa_family = AF_UNIX;
    strcpy(name.sa_data, "127.0.0.1");
    adrlen = strlen(name.sa_data) + sizeof(name.sa_family);

    if(connect(sock, &name, adrlen) < 0) {
        printf("\nclient connection failure %m", errno);
        exit(1);
    }

    cout<<"\nSuccessful connection\n";

    //set nonblock
    set_nonblock(sock);

    std::string out;
    char* in = new char[80];
    int numRead;
    int numSent;


    while(out.compare("quit")) {

        //clear in
        for(int i=0;i<80;i++)
            in[i] = '\0';


        numRead = recv(sock, in, 80, 0);

        if(numRead > 0)
            cout<<"\nData read from server - "<<in;


        cout<<"\n";
        out.clear();
        cin>>out;
        cin.get();

        //if we typed something, send it
        if(strlen(out.c_str())) {
            numSent = send(sock, out.c_str(), strlen(out.c_str()), 0);
            cout<<"\n"<<numSent<<" bytes sent";
        }

    }   //end while


    cout<<"\nExiting normally\n";
    return 0;
}

每当我运行它,服务器仍然等待我发送的东西将读取并输出客户端已发送的内容。我想让服务器或客户端能够在我键入时立即发送消息,并让另一个读取并输出消息。我认为无阻塞套接字是答案,但也许我只是做错了什么?

Whenever I run it, the server still waits for me to send something before it will read and output what the client has sent. I want either the server or client to be able to send the message as soon as I type it, and have the other read and output the message at that time. I thought non-blocking sockets was the answer, but maybe I am just doing something wrong?

此外,我使用的是文件,而不是我的127.0.0.1地址作为sockaddr的数据。如果这不是如何正确使用,请随意说这样(它工作以前如何与一个文件,所以我只是保持这样的文件)。

Also, I was using a file instead of my 127.0.0.1 address as the sockaddr's data. If that is not how it should be properly used, feel free to say so (it worked how it worked previously with a file so I just kept it like that).

推荐答案


每当我运行它,服务器仍然等待我发送它会读取并输出客户端发送的内容。

Whenever I run it, the server still waits for me to send something before it will read and output what the client has sent.

好吧,这就是你写的。

Well, that is how you wrote it. You block on IO from stdin, and then and only then do you send/receive.

cin>>out;
cin.get();

此外,您正在使用本地套接字(AF_UNIX),它在文件系统中为进程创建一个特殊文件通信 - 这是一个不同于IP的机制,绝对不是你的问题中指出的TCP。我假设您可以命名文件 127.0.0.1 ,但这真的没有意义,意味着你的部分,因为这是一个IP环回地址的混乱。

Also, you are using a local socket (AF_UNIX) which creates a special file in your filesystem for interprocess communication - this is a different mechanism than IP, and is definitely not TCP as you indicate in your question. I suppose you could name the file 127.0.0.1, but that really doesn't make sense and implies confusion on your part, because that is an IP loopback address. You'll want to use AF_INET for IP.

对于unix网络上的优秀入门指南,我建议您使用 http://beej.us/guide/bgnet/

For an excellent starter guide on unix networking, I'd recommend http://beej.us/guide/bgnet/

如果您想显示邮件收到的是独立于您的cin语句,或者fork()关闭一个单独的进程来处理您的网络IO,或者使用一个单独的线程。

If you want the display of messages received to be independant of your cin statements, either fork() off a seperate process to handle your network IO, or use a separate thread.

您可能感兴趣select ()。在我看来,非阻塞套接字通常是一个黑客,正确使用select()或poll()通常是更好的设计和更灵活(和更便携)。尝试

You might be interested in select(). In my opinion non-blocking sockets are usually a hack, and proper usage of select() or poll() is generally much better design and more flexible (and more portable). try


man select_tut

man select_tut

信息。

这篇关于BSD套接字 - 如何使用非阻塞套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆