1

Linux n00b 在这里。所以大约一个月前,我安装了 emacs 和 gcc/g++ 编译器并开始编程。我在网上找到了一些回显服务器程序的代码,复制并编译它以测试网络功能。它编译了,但是当我尝试运行它时,我收到了错误消息:Segmentation fault(core dumped)。当我仔细查看调试器详细信息时,“fwrite()”函数出现错误。我在编译和创建输出文件时将代码链接到库libstdc++.a,所以它确实让我想知道实际库函数中是否存在一些严重错误,我需要返回,找到函数 .c 源代码,然后将它们添加到标题中以使其工作。代码贴在下面。其他人有这个问题吗?

#include <sys-socket.h>       /*  socket definitions        */
#include <sys-types.h>        /*  socket types              */
#include <netinet-in.h>        /*  inet (3) functions         */
#include <unistd.h>           /*  misc. UNIX functions      */
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <ether.h>
#include <string.h>


/*  Global constants  */

#define ECHO_PORT          2002
#define MAX_LINE           1000
#define LISTENQ            5


ssize_t Readline(int sockd, char *vptr,size_t maxlen) {
    ssize_t n, rc;
    char*    c;
    msghdr* buffer;

    buffer->msg_iov->iov_base = vptr;
    buffer->msg_iov->iov_len  = maxlen;

    for ( n = 1; n < maxlen; n++ ) {

      if ( (rc = recvmsg(sockd,buffer, 1)) == 1 ) {
    c = buffer->msg_iov->iov_base++;
        if (*c == '\n' )
        break;
    }
    else if ( rc == 0 ) {
        if ( n == 1 )
        return 0;
        else
        break;
    }
    else {
        if (rc < 0 )
        continue;
        return -1;
    }
    }

    buffer->msg_iov->iov_base = 0;
    return n;
}


/*  Write a line to a socket  */

ssize_t Writeline(int sockd, char *vptr) {
     msghdr     *buffer;


     buffer->msg_iov->iov_base = vptr;
     size_t      nleft = buffer->msg_iov->iov_len;
     ssize_t     nwritten;

    while ( nleft > 0 ) {
    if ( (nwritten = sendmsg(sockd, buffer, nleft)) < 0 ) {
          return -1;
    }
    nleft  -= nwritten;
    buffer += nwritten;
    }

    return nwritten;
}

int main(int argc, char *argv[]) {
    int       list_s;                /*  listening socket          */
    int       conn_s;                /*  connection socket         */
    short int port;                  /*  port number               */
    struct    sockaddr_in servaddr;  /*  socket address structure  */
    char     *endptr;                /*  for strtol()              */
    char      buffer[MAX_LINE];




    port = 5000;


    /*  Create the listening socket  */

    if ( (list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
    fprintf(stderr, "ECHOSERV: Error creating listening socket.\n");
    exit(EXIT_FAILURE);
    }


    /*  Set all bytes in socket address structure to
        zero, and fill in the relevant data members   */

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(port);


    /*  Bind our socket addresss to the 
    listening socket, and call listen()  */

    if ( bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
    fprintf(stderr, "ECHOSERV: Error calling bind()\n");
    exit(EXIT_FAILURE);
    }

    if ( listen(list_s, LISTENQ) < 0 ) {
    fprintf(stderr, "ECHOSERV: Error calling listen()\n");
    exit(EXIT_FAILURE);
    }


    /*  Enter an infinite loop to respond
        to client requests and echo input  */

    while ( 1 ) {

    /*  Wait for a connection, then accept() it  */

    if ( (conn_s = accept(list_s, NULL, NULL) ) < 0 ) {
        fprintf(stderr, "ECHOSERV: Error calling accept()\n");
        exit(EXIT_FAILURE);
    }


    /*  Retrieve an input line from the connected socket
        then simply write it back to the same socket.     */

    Readline(conn_s, buffer, MAX_LINE-1);
    Writeline(conn_s, buffer);


    /*  Close the connected socket  */

    if ( shutdown(conn_s,0) < 0 ) {
        fprintf(stderr, "ECHOSERV: Error calling close()\n");
        exit(EXIT_FAILURE);
    }
    }
}
4

3 回答 3

4
ssize_t Writeline(int sockd, char *vptr) {
     msghdr     *buffer;


     buffer->msg_iov->iov_base = vptr;

您的指针缓冲区未初始化。您可能会查看此代码片段以正确执行此操作:

      /* This structure contains parameter information for sendmsg.   */
   struct msghdr mh;

      /* The message header contains parameters for sendmsg.    */
   mh.msg_name = (caddr_t) &dest;
   mh.msg_namelen = sizeof(dest);
   mh.msg_iov = iov;
   mh.msg_iovlen = 3;
   mh.msg_accrights = NULL;            /* irrelevant to AF_INET */
   mh.msg_accrightslen = 0;            /* irrelevant to AF_INET */

   rc = sendmsg(s, &mh, 0);            /* no flags used         */
   if (rc == -1) {
      perror("sendmsg failed");
      return -1;
   }
   return 0;
}

发送消息

于 2013-08-25T16:08:26.313 回答
1

你真的复制了这个,还是你复制了一些位然后自己粘贴在一起?

至少修复到它不会自行崩溃的程度并不是很难 - 我没有进一步了解,因为我的防火墙设置太严格,无法启动程序并使用随机端口,而我没有感觉就像为了测试您的代码而弄乱了我的防火墙设置。

因此,正如所指出的,msghdr *buffer;意味着指针buffer未初始化。简单的解决方法是不使用指针,而是使用buffer您需要时的地址。然后你需要有一个iov数据结构。

所以,在接收中,你最终会得到这样的结果:

msghdr   buffer;
iovec    iov;

buffer.msg_iov = &iov;
...
if ( (rc = recvmsg(sockd, &buffer, 1)) == 1 ) {
    c = vptr++;
    buffer.msg_iov->iov_base = vptr;

注意&缓冲区的前面。我还更改了下一行,因为它是在 C++ 中没有明确定义++void指针上做的,所以编译器给出了警告。(还有一个buffer未初始化的警告)。

`WriteLine 函数中需要类似的处理。

iovec    iov;

buffer.msg_iov = &iov;
buffer.msg_iov->iov_base = vptr;
size_t      nleft = MAX_LINE;

... 
   if ( (nwritten = sendmsg(sockd, &buffer, nleft)) < 0 ) {
   ....

   nleft  -= nwritten;
   vptr += nwritten;
   buffer.msg_iov->iov_base = vptr;

同样,自增iov_base是自增 a void *,自从我在上面写它以来还没有定义,所以需要确保指针具有不同的类型 - 重用vptr在这里很合适。

顺便说一句,我将nleft设置更改为MAX_LINE,因为您没有传递线的大小。我建议您更改它,以便它确实将大小作为参数,类似于ReadLine函数。

最后,请帮自己一个忙,并-Wall -Werror在编译代码时使用——这意味着当你做“愚蠢”的事情时会收到警告——它可能有效,但也可能无效。几乎所有来自编译器的警告都是有用的。

请记住,在 C 或 C++ 中使用指针时,应确保它指向某个对象。只是写T* ptr;只是给你一个指针,指针没有附加内存,所以在你使用那个指针之前,你应该以某种方式分配它。

我远不能相信这涵盖了所有内容 - 但它应该让你在某种程度上让某些东西工作起来。

于 2013-08-25T16:34:33.770 回答
1

您没有在and函数中设置buffer指针变量。Writeline()ReadLine()

ssize_t Writeline(int sockd, char *vptr) {
     msghdr     *buffer;

     //this is not appropriate as buffer does not point to appropriate memory.
     buffer->msg_iov->iov_base = vptr;

     size_t      nleft = buffer->msg_iov->iov_len;
     ssize_t     nwritten;
     ...    
    return nwritten;
}

访问buffer->msg_iov->iov_basebuffer->msg_iov->iov_lenbuffer至是不适当的而不分配它或设置到适当的内存是无效的。

于 2013-08-25T16:07:56.620 回答