当程序之前运行良好时,C 中的 TCP 分段错误(核心转储) [英] TCP segmentation fault (core dumped) in C when the program worked fine before

查看:20
本文介绍了当程序之前运行良好时,C 中的 TCP 分段错误(核心转储)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了开始制作 TCP 程序,我从 GeeksForGeeks 复制了代码.在我运行它几次之后它运行良好......然后它突然没有......

I copied the code from GeeksForGeeks in order to start making a TCP program. After i ran it a couple of times it worked perfectly... then it suddenly didn't...

服务器:

#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr

void func(int sockfd);

int main()
{
    int sockfd, connfd, len;
    struct sockaddr_in servaddr, cli;

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...
");
        exit(0);
    }
    else
        printf("Socket successfully created..
");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...
");
        exit(0);
    }
    else
        printf("Socket successfully binded..
");

    // Now server is ready to listen and verification
    if ((listen(sockfd, 1)) != 0) {
        printf("Listen failed...
");
        exit(0);
    }
    else
        printf("Server listening..
");
    len = sizeof(cli);

    // Accept the data packet from client and verification
    connfd = accept(sockfd, (SA*)&cli, &len);
    if (connfd < 0) {
        printf("server acccept failed...
");
        exit(0);
    }
    else
        printf("server acccept the client...
");

    // Function for chatting between client and server
    func(connfd);

    // After chatting close the socket
    close(sockfd);
}

void func(int sockfd)
{
    char buff[MAX];
    int n;
    for(;;)
    {
        bzero(buff, sizeof(buff));
        n=0;

        read(sockfd, buff, sizeof(buff));
        printf("%s", buff);

    }

}

客户:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr

void func(int sockfd);

int main()
{
    int sockfd, connfd;
    struct sockaddr_in servaddr, cli;

    // socket create and varification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...
");
        exit(0);
    }
    else
        printf("Socket successfully created..
");
    bzero(&servaddr, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = htons(PORT);

    // connect the client socket to server socket
    if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
        printf("connection with the server failed...
");
        exit(0);
    }
    else
    {
        printf("connected to the server..
");
    }
    printf("boop");
    // function for chat
    func(sockfd);

    // close the socket
    close(sockfd);
}

void func(int sockfd)
{
    printf("Heelloo");
    char buff[MAX];
    int n;
    for(;;)
    {
        bzero(buff, sizeof(buff));
        n=0;

        printf("To client: ");
        while((buff[n++] = getchar()) != '
');
        write(sockfd, buff, sizeof(buff));


    }
}

函数不完整,但问题似乎出现在客户端 main() 中的 func() 调用之前.任何帮助将不胜感激!

the function is incomplete but the problem appears to be right before the func() call in client main(). Any help would be appreciated!

推荐答案

    write(sockfd, buff, sizeof(buff));

每一本教如何正确使用套接字的教科书都会解释说,你绝对不能保证,无论如何,write() 会实际将请求的字节数写入套接字.write() 的返回值表示实际写入的字节数(可以小于其第三个参数请求的数字),写入套接字的代码必须正确实现必要的如果需要,继续将剩余数据写入套接字的逻辑.

Every textbook that teaches how to correctly use sockets will explain that you have absolutely no guarantees, whatsoever, that write() will actually write the requested number of bytes to the socket. The return value from write() indicates the number of bytes that were actually written (which can be less than the number requested by its third parameter), and the code that writes to sockets must correctly implement the necessary to logic to continue writing the remaining data to the socket, if so needed.

另外,这里并没有初始化整个buff,只是初始化了它的初始部分,所以这会尝试写入整个buff,这在技术上是未定义的行为.

Additionally, not the entire buff is initialized here, only the initial part of it, so this attempts to write the entire buff, which is technically undefined behavior.

   read(sockfd, buff, sizeof(buff));

我对 write() 的解释同样适用于 read().您必须检查 read() 的返回值以确定从套接字实际读取了多少.read() 完全有可能最终只读取第一个字符;buff 的其余部分未初始化,包含随机垃圾,并且以下 printf 对正确 '' 的搜索终止字符串注定要彻底失败,崩溃.

The same thing that I explained about write() also applies to read() as well. You must check the return value from read() to determine how much was actually read from the socket. It's entirely possible that the read() ends up reading just the first character; the rest of the buff is uninitialized, and contains random garbage, and the following printf's search for a properly ''-terminated strings is doomed to an utter failure, and a crash.

每次运行程序时,由于各种原因,客户端和服务器可能最终会从套接字读取和写入不同数量的字节.这解释了为什么您观察到该程序随机失败,并且看似有效,但没有可预测的模式.

Each time you run your program, for various reasons you're likely end up with different number of bytes both read and written from the socket, by both the client and server. This explains why you observed this program to randomly fail, and seemingly work, with no predictable pattern.

一般来说,像 GeeksForGeeks 这样的网站并不是用来学习编程的.他们缺乏适当的教程、技术信息和说明材料.正如我在开头提到的,学习网络编程和其他技术主题的最佳方式是通过有指导的、基于教科书的学习课程.你能在 GeeksForGeeks 上找到任何东西吗,你从哪里复制了这个程序,说明你必须检查 readwrite 的返回值?不,因为它不是用来作为学习材料的,而是每个网络编程教程必须不仅要解释这一点,还要解释其他几个基本的相关概念.

In general, sites like GeeksForGeeks are not meant to be used as means of learning programming; they lack proper tutorials, technical information, and explanatory material. As I mentioned in the beginning, the best way to learn network programming, and other technical topics, is through guided, textbook-based study course. Can you find anything on GeeksForGeeks, where you copied this program from, explain that you must check the return value from read and write? No, because it is not meant to be used as a learning material, but every tutorial on network programming must explain not just this, but also several other fundamental, related concepts as well.

这篇关于当程序之前运行良好时,C 中的 TCP 分段错误(核心转储)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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