C套接字程序 - 如何在更新stdout读取时接受用户输入?

时间:2023-01-31 15:41:04

I have written a little irc bot application in C. It just writes out the server messages to the screen. This is just accomplished with a while loop that reads from the server filedescriptor. How can I concurrently accept input? I would like to now extend it to accept user input so that it can be used as a client application. I am new to C development so I am not sure how this is accomplished. Can someone provide me with an example or point me in the direction to some documentation?

我在C中编写了一个小的irc bot应用程序。它只是将服务器消息写入屏幕。这只是通过从服务器文件描述符读取的while循环来完成的。我如何同时接受输入?我现在想扩展它以接受用户输入,以便它可以用作客户端应用程序。我是C开发的新手,所以我不确定这是如何实现的。有人能给我一个例子,还是指向一些文档的方向?

I basically would like to mimic a telnet application. The stdout is updated and the user can provide server commands at the console.

我基本上想模仿一个telnet应用程序。 stdout已更新,用户可以在控制台上提供服务器命令。

Any help/advise would be greatly appreciated.

任何帮助/建议将不胜感激。

EDIT

I am developing in a Unix environment.

我正在Unix环境中开发。

Thanks

3 个解决方案

#1


4  

Avoid multiprocess and multi-threaded programming if you can. That road leads to pain. Use event driven programming. For the type of thing you are wanting to do, event driven programming is much easier, and will perform just as well. The two main ways in C to do event driven programming (related to I/O) are select and poll.

如果可以的话,避免使用多进程和多线程编程。那条路会导致痛苦。使用事件驱动编程。对于您想要做的事情类型,事件驱动编程更容易,并且也会表现得更好。 C进行事件驱动编程(与I / O相关)的两种主要方式是select和poll。

Here is working example of using select:

以下是使用select的工作示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

int
main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval, len;
    char buf[4096];

    while (1) {
        /* Watch stdin (fd 0) to see when it has input. */
        FD_ZERO(&rfds);
        FD_SET(0, &rfds);

        /* Wait up to five seconds. */
        tv.tv_sec = 5;
        tv.tv_usec = 0;

        retval = select(1, &rfds, NULL, NULL, &tv);
        /* Don't rely on the value of tv now! */

        if (retval == -1) {
            perror("select()");
            exit(EIO);
        } else if (retval) {
            printf("Data is available now.\n");
        } else {
            printf("No data within five seconds.\n");
            continue;
        }
        if (FD_ISSET(0, &rfds)) {
            len = read(0, buf, 4096);
            if (len > 0) {
                buf[len] = 0;
                printf("Got data on stdin: %s\n", buf);
            } else {
                // fd closed
                perror("read()");
                exit(EIO);
            }

        }
    }
}

FD_SET is used to create the list of file-descriptors you want to select on (get events from). After select returns successfully (meaning there is an event to process), you use FD_ISSET to find the file-descriptors that caused events. In your case you are going to have an open socket file-descriptor that you will add to the set and process appropriately.

FD_SET用于创建要选择的文件描述符列表(从中获取事件)。 select成功返回后(意味着有一个要处理的事件),您使用FD_ISSET查找导致事件的文件描述符。在您的情况下,您将拥有一个打开的套接字文件描述符,您将添加到该组并进行适当的处​​理。

Useful documentation include the following man pages:

有用的文档包括以下手册页:

  • man 2 select
  • 男人2选择

  • man 2 poll
  • 男子2民意调查

  • man 3 read
  • 男人3读

  • man 3 open
  • 男人3开

#2


2  

You want to monitor both socket, and stdin. If thats right, have a look at the select() system call here: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

您想监视套接字和标准输入。如果没错,请看一下select()系统调用:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

#3


-2  

There is a little thing called multi-threading. Multithreading (in C++) depends entirely on either the operating system, or an external library.

有一个叫做多线程的小东西。多线程(在C ++中)完全取决于操作系统或外部库。

If you are using windows, then you could use beginthread() and endthread() defined in "Windows.h".

如果您使用的是Windows,则可以使用“Windows.h”中定义的beginthread()和endthread()。

It is fairly easy to use.

它相当容易使用。

#1


4  

Avoid multiprocess and multi-threaded programming if you can. That road leads to pain. Use event driven programming. For the type of thing you are wanting to do, event driven programming is much easier, and will perform just as well. The two main ways in C to do event driven programming (related to I/O) are select and poll.

如果可以的话,避免使用多进程和多线程编程。那条路会导致痛苦。使用事件驱动编程。对于您想要做的事情类型,事件驱动编程更容易,并且也会表现得更好。 C进行事件驱动编程(与I / O相关)的两种主要方式是select和poll。

Here is working example of using select:

以下是使用select的工作示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

int
main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval, len;
    char buf[4096];

    while (1) {
        /* Watch stdin (fd 0) to see when it has input. */
        FD_ZERO(&rfds);
        FD_SET(0, &rfds);

        /* Wait up to five seconds. */
        tv.tv_sec = 5;
        tv.tv_usec = 0;

        retval = select(1, &rfds, NULL, NULL, &tv);
        /* Don't rely on the value of tv now! */

        if (retval == -1) {
            perror("select()");
            exit(EIO);
        } else if (retval) {
            printf("Data is available now.\n");
        } else {
            printf("No data within five seconds.\n");
            continue;
        }
        if (FD_ISSET(0, &rfds)) {
            len = read(0, buf, 4096);
            if (len > 0) {
                buf[len] = 0;
                printf("Got data on stdin: %s\n", buf);
            } else {
                // fd closed
                perror("read()");
                exit(EIO);
            }

        }
    }
}

FD_SET is used to create the list of file-descriptors you want to select on (get events from). After select returns successfully (meaning there is an event to process), you use FD_ISSET to find the file-descriptors that caused events. In your case you are going to have an open socket file-descriptor that you will add to the set and process appropriately.

FD_SET用于创建要选择的文件描述符列表(从中获取事件)。 select成功返回后(意味着有一个要处理的事件),您使用FD_ISSET查找导致事件的文件描述符。在您的情况下,您将拥有一个打开的套接字文件描述符,您将添加到该组并进行适当的处​​理。

Useful documentation include the following man pages:

有用的文档包括以下手册页:

  • man 2 select
  • 男人2选择

  • man 2 poll
  • 男子2民意调查

  • man 3 read
  • 男人3读

  • man 3 open
  • 男人3开

#2


2  

You want to monitor both socket, and stdin. If thats right, have a look at the select() system call here: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

您想监视套接字和标准输入。如果没错,请看一下select()系统调用:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

#3


-2  

There is a little thing called multi-threading. Multithreading (in C++) depends entirely on either the operating system, or an external library.

有一个叫做多线程的小东西。多线程(在C ++中)完全取决于操作系统或外部库。

If you are using windows, then you could use beginthread() and endthread() defined in "Windows.h".

如果您使用的是Windows,则可以使用“Windows.h”中定义的beginthread()和endthread()。

It is fairly easy to use.

它相当容易使用。