0

我已经创建了一个套接字,我正在尝试接受连接。一切正常。但是,输出让我对以下代码的工作方式感到困惑。

      // this a server program
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <sys/un.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #include <wait.h>

    #define LISTENQ (1024)

    int main(void) {

       int lstn_sock, conn_sock;
       struct sockaddr_in my_serv;
       short int pnum = 4080;

       // create listening socket
       if( (lstn_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Error (socket): %s\n",strerror(errno));
        exit(1);
       }

       // initialize socket address
       memset( &my_serv, 0, sizeof(my_serv) );
       my_serv.sin_family = AF_INET;
       my_serv.sin_addr.s_addr = INADDR_ANY;
       my_serv.sin_port = htons(pnum);

       // associate address with socket. 
       if( bind(lstn_sock, (struct sockaddr *) &my_serv, sizeof(my_serv)) < 0){
        printf("Error (bind): %s\n",strerror(errno));
        exit(1);
       }
        //printf("lstn_sock: %d\n",lstn_sock);
       // start listening to socket
       if( listen(lstn_sock, LISTENQ) < 0){
        printf("Error (listen): %s\n",strerror(errno));
        exit(1);
       }

       // make it a daemon
       while(1){
        // retrieve connect request and connect
        if( (conn_sock = accept(lstn_sock, NULL, NULL)) < 0){
           printf("Error (accept): %s\n",strerror(errno));
           exit(1);
        }

        printf("The server says hi!\n");

        // close connected socket
        if( close(conn_sock) < 0){
           printf("Error (close): %s\n",strerror(errno));
           exit(1);
        }
       }

    return 0;

    }

@ubuntu:$ ./my_code & @ubuntu:$ telnet localhost 4080

以下是上述代码的 2 个不同输出:
Output1
Trying ::1...
Trying 127.0.0.1..
Connected to localhost。
转义字符是 '^]'。
服务员打招呼!
外部主机关闭连接。

Output2
Trying ::1...
Trying 127.0.0.1..
服务器打招呼!
连接到本地主机。
转义字符是 '^]'。
外部主机关闭连接。

有人可以解释“服务器打招呼!”移动的原因吗?
在输出中。

4

2 回答 2

2

我猜你是在后台启动你的服务器,并在同一个终端中使用 telnet 来测试它。

您的服务器将问候语打印到标准输出,telnet 也写入标准输出。它们是两个独立的进程,将独立(可能同时)调度。您无法预测输出在终端上出现的确切顺序。

于 2012-04-21T15:14:31.060 回答
1

我写了一个更长的答案,但随后出现内核恐慌!!!!非常讨厌我的MOBO。但这里有一个较短的重新上限。

我看到您的问题已解决,但只是要清楚:

你可以阅读- 和潜艇。

您正在使用终端。终端通常具有三个

  • 标准输入
  • 标准输出
  • 标准错误

当您启动服务器程序时,会在该终端中启动一个进程。

该进程从终端进程继承各种“东西”,如环境变量、限制等。服务器也成为 shell 的进程。shell 本身通常是更高进程的子进程,依此类推。

当您使用与号时,该进程被置于后台,但仍然是同一终端的子进程。

对任一流的写入将写入与启动该进程的 shell相同的流。

在典型的服务器/客户端场景中,您不会写入stdout发送消息。服务器的stdout绑定到服务器环境(/proc/[pid]/fd/...)。客户端,通常在不同的系统上,(通常)无法访问服务器上的任何东西 - 因此是套接字的整个概念 - 独立系统之间的通信。这就是为什么您改为写入连接的原因。


使用各种 Linux 工具快速查看您的案例;

如果你发布pstree,你可以很容易地看到这一点;像(删除很多):

$ ./server 4082 &
[1] 2795 <-- PID OF SERVER
$ pstree -p
init(1)─┬─ ...
        :
        ├─gnome-terminal(2369)─┬─bash(2374)───mplayer(2459)───mplayer(2460)
        │                      ├─bash(2586)───pstree(2779)
        │                      ├─bash(2646)
        │                      ├─bash(2705)───server(2795) <-- YOUR SERVER
        │                      ├─gnome-pty-helpe(2373)
        │                      ├─{gnome-terminal}(2371)
        │                      ├─{gnome-terminal}(2372)
        │                      └─{gnome-terminal}(2375)
        :
$ telnet localhost 4082  <--- IN SAME TERMINAL
$ pstree -p
init(1)─┬─ ...
        :
        ├─gnome-terminal(2369)─┬─bash(2374)───mplayer(2459)───mplayer(2460)
        │                      ├─bash(2586)───pstree(2779)
        │                      ├─bash(2646)
        │                      ├─bash(2705)─┬─server(2795) <-- YOUR SERVER
        │                      │            └─telnet(2797) <-- TELNET SAME SHELL
        │                      ├─gnome-pty-helpe(2373)
        │                      ├─{gnome-terminal}(2371)
        │                      ├─{gnome-terminal}(2372)
        │                      └─{gnome-terminal}(2375)
        :

现在。服务器和 shell共享相同的 bash,因此最终用户输出相同- stdout...</p>

您可以通过各种方式监视进程的不同流。一种简单的方法是使用strace

$ sudo strace -ewrite -p 12345

哪里12345是进程的PID。IE;

$ sudo strace -e write=0,1,3,4 -p 2797
Process 2797 attached - interrupt to quit
select(4, [0 3], [], [3], NULL)         = 1 (in [0])
read(0, "frack!\n", 8129)               = 7
select(4, [0 3], [3], [3], {0, 0})      = 1 (out [3], left {0, 0})
send(3, "frack!\r\n", 8, 0)             = 8
 | 00000  66 72 61 63 6b 21 0d 0a                           frack!..          |
于 2012-04-21T19:10:17.097 回答