【问题标题】:Can anyone see why my log file keeps ending up empty here?谁能看到为什么我的日志文件在这里一直是空的?
【发布时间】:2016-03-10 13:06:45
【问题描述】:

我正在编写一些代码来为分配创建一个小型 UDS 服务器。客户端将与携带某些消息的服务器建立特定系列的连接。基本上,如果这些消息按顺序出现在我们的日志文件中,那么我们就都准备好了。但是每次运行时我的日志文件都会完全空白,我不确定我明白为什么。

这是我的代码:

// forward declarations
int error_msg( char * msg );
int usage( char name[] );

// a function to be executed by each thread
void * recv_log_msgs( void * arg );

// globals
FILE * log_fd; // opened by main() but accessible by each thread
typedef struct sockaddr SA;

void * recv_log_msgs( void * arg ) //Thread Routine
{
    // loops to receive messages from a client;
    // when the connection is closed by the client,
    // close the socket
    int clientfd = *((int *)arg);
    char buffer[1500];
    memset(buffer, 0, 1500);
    int currentPos = 0;
    int bytesRec;
    int recvng = 1;

    while(recvng){
        bytesRec = recv(clientfd, buffer, 1500-currentPos, 0);
        currentPos += bytesRec;
        if(buffer[currentPos - 1] == '\n')
            recvng = 0;
    }

    fprintf(log_fd, "LOGGER %d %s", clientfd, buffer);
    close(clientfd);
    return NULL;
}


int main( int argc, char * argv[] )
{
    if ( argc != 3 )
        return usage( argv[0] );

    log_fd = fopen(argv[1], "a");

    // create a server socket
    // domain (i.e., family) is AF_UNIX
    // type is SOCK_STREAM

    socklen_t clientLength = sizeof(struct sockaddr_un);
    struct sockaddr_un clientAddr;
    clientAddr.sun_family = AF_UNIX;
    strcpy(clientAddr.sun_path, argv[2]);

    pthread_t tid;

    int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);     

    // unlink the UDS path)
    unlink(argv[2]);

    // bind the server socket
    bind(listenfd, (SA *)&clientAddr, clientLength);    

    // listen
    listen(listenfd, 1024);
    // loop to wait for connections;
    // as each connection is accepted,
    // launch a new thread that calls
    // recv_log_msgs(), which receives
    // messages and writes them to the log file
    while(1){
        printf( "Waiting for a connection on UDS path %s...\n", argv[2] );
        int * clientfdp = malloc(sizeof(int));
        *clientfdp = accept(listenfd, (SA *) &clientAddr, &clientLength);
        pthread_create(&tid, NULL, recv_log_msgs, clientfdp);
        printf("%d",errno);
        return 0;
    }

    // when the loop ends, close the listening socket
    close(listenfd);        

    // close the log file
    fclose(log_fd);

    return 0;
}

写入日志发生在顶部函数recv_log_msgs。我是 C 的新手,我经常被文件处理方式的细节所困扰,或者认为内存数组的级别太高,诸如此类。鉴于我的代码,我真的不明白为什么应该写 nothing。我什至试图通过在客户端文件描述符上调用recv() 来正确“读取”数据?我是否正确使用了缓冲区?

【问题讨论】:

  • 你试过使用调试器吗?
  • @MohitJain 这当然是我的第一直觉,我试过了。但是进行所有连接调用的客户端的行为是在一个可执行文件中,该可执行文件是通过分配提供给我们的。所以我不确定如何调试它。当我尝试时,它总是一直走到最后,并说它没有要显示的行号。
  • 您可以尝试在 while 循环中放置一个 print 来查看 bytesRec 是否以及如何被填满。另外,你应该检查recv的返回值。
  • 您的代码正在使用来自多个线程的fprintf(log_fd, ....)。这些调用需要同步(例如,使用互斥锁)。
  • @Peter 但是这不是join 的用途吗

标签: c multithreading sockets


【解决方案1】:

if(buffer[currentPos - 1] == '\n') 不能工作。是否找到换行符取决于获得的块大小。

循环永远不会中断。您需要在收到的块中搜索 所有 个字符。现在这只是检查一个字符,并且是任意选择的一个。

【讨论】:

  • 那么在缓冲区中检查指定字符的最简单方法是什么?
  • 理想情况下,您可以找到一个标准库函数来在缓冲区中搜索换行符。如果这不可用,您编写一个循环来检查每个字符。
  • 整个while(recvng) 循环被破坏。所有recv 调用都会覆盖从之前调用中读取的数据。
  • @AndrewHenle 对,我什至没有验证这一点。可能他应该在收到数据后立即将其写出。这使他免于指针/索引计算。
  • @AndrewHenle 我不明白为什么。我该如何解决?我认为这是我的主要问题。
猜你喜欢
  • 2012-05-13
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 2017-12-01
  • 1970-01-01
相关资源
最近更新 更多