错误:“:连接被拒绝”| C 中的套接字编程

问题描述 投票:0回答:1

我必须为我的一个讲座做一项作业,其中我必须用 C 语言在客户端和服务器程序之间创建连接。服务器程序和客户端程序必须在不同的 PC 上运行。启动 server.c 后:

  1. gcc 服务器.c -o 服务器
  2. ./server // 数字是 packet.h 的一部分 服务器停止在“Listening...”,这是正确的。

之后我启动了 client.c:

  1. gcc client.c -o 客户端
  2. ./客户 检查 connect() 函数后,程序会抛出错误“:连接被拒绝”。一定有问题,但我无法解决它。

我试图找出确切的问题。以下是我已经尝试过的一些事情:

  1. 服务器 100% 在我的本地互联网上。我尝试使用“netcat”搜索服务器,服务器就在那里。
  2. 我总是在我的家庭网络中使用大于 5000 的端口,在我的大学网络中使用大于 50000 的端口(唯一可以使用的端口,我的教授告诉我的)。
  3. 我在ubuntu上工作,我总是在ipv6后面写“%eth0”。
  4. 我检查了一堆其他代码,我的代码看起来几乎相同。
  5. 我尝试调试“client.c”文件,但 connect() 函数总是返回 -1。我认为一定有问题,但我无法解决。

这是我的代码: 服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
// #include <libc.h>

#include "packet.h"

int main(int argc, char *argv[]){
    if(argc != 4){  // Test ob 4 Programmargumente mitgegeben wurden
        fprintf(stderr, "- Error: %s <IPv6 address> <port> <sNummer>\n", argv[0]);
        exit(1);
    }

    struct packet received_packet, send_packet;
    const char *ip = argv[1];

    char* endptr;

    long port_long = strtol(argv[2], &endptr, 10);
    if(*endptr != '\0' || port_long < 0 || port_long > UINT16_MAX){
        fprintf(stderr, "- invalid port number: %s\n", argv[2]);
        exit(1);
    }
    uint16_t port =(uint16_t)port_long;

    long sNummer_long = strtol(argv[3], &endptr, 10);
    if(*endptr != '\0' || sNummer_long < 0 || sNummer_long > UINT32_MAX){
        fprintf(stderr, "- invalid sNummer: %s\n", argv[3]);
        exit(1);
    }
    send_packet.sNummer = (uint32_t)sNummer_long; 

    int csocket;                
    struct sockaddr_in6 addr;   
    socklen_t addrsize;          
    char test[1024];            

    csocket = socket(AF_INET6, SOCK_STREAM, 0);
    
    if(csocket < 0 ){ // Test ob TCP-Socket erstellt wurde
        perror("- socket error\n");
        exit(1);
    }
    printf("+  TCP server socket created\n");

    memset(&addr, 0, sizeof(addr)); 
    addr.sin6_family = AF_INET6;      
    addr.sin6_port = htons(port);            
    inet_pton(AF_INET6, ip, &addr.sin6_addr); 

    if( connect(csocket, (struct sockaddr *) &addr, sizeof(addr)) < 0 ){
        perror("- could not connect to server\n");
        exit(1);
    }
    printf("+ Connected to server %s on port %d\n",ip, port);

    printf("\n ----- message -----\n");
    printf("text: ");
    scanf("%s",send_packet.text);

    printf("s%d > %s\n",send_packet.sNummer, send_packet.text);
    send(csocket, &send_packet, sizeof(send_packet), 0); 

    ssize_t bytesRead = recv(csocket, &received_packet, sizeof(received_packet), 0); 
    if( bytesRead <= 0 ){
        perror("- error receiving data from server\n");
    }
    test[bytesRead] = '\0';
    printf("\n ----- Server -----\n");
    printf("s%d > %s\n",received_packet.sNummer,received_packet.text);

    close(csocket);
    printf("\n+ disconnected from server\n");

    return 0;
}

客户端.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
// #include <libc.h>

#include "packet.h"

#define BACKLOG     5

int main(int argc, char *argv[]){
    if(argc != 3){  // Test ob auch 3 Programmargumente mitgegeben wurden
        fprintf(stderr, "- Error: %s <port> <sNummer>\n",argv[0]);
        exit(1);
    }

    struct packet received_packet, response_packet;
    char* endptr;

    long port_long = strtol(argv[1], &endptr, 10);
    if(*endptr != '\0' || port_long < 0 || port_long > UINT16_MAX){
        fprintf(stderr, "- invalid port number: %s\n", argv[1]);
        exit(1);
    }
    uint16_t port =(uint16_t)port_long;

    long sNummer_long = strtol(argv[2], &endptr, 10);
    if(*endptr != '\0' || sNummer_long < 0 || sNummer_long > UINT32_MAX){
        fprintf(stderr, "- invalid sNummer: %s\n", argv[2]);
        exit(1);
    }
    response_packet.sNummer = (uint32_t)sNummer_long;

    int server_socket, client_socket;   
    struct sockaddr_in6 s_addr, c_addr; 
    socklen_t c_addrsize;               
    char test[1024];                    

    server_socket = socket(AF_INET6, SOCK_STREAM, 0); 
    
    if(server_socket < 0 ){ 
        perror("- socket error\n");
        exit(1);
    }
    printf("+  TCP server socket created\n");

    memset(&s_addr, 0, sizeof(s_addr)); 
    s_addr.sin6_family = AF_INET6;      
    s_addr.sin6_port = htons(port);    
    s_addr.sin6_addr = in6addr_any;     

    if(bind(server_socket, (struct sockaddr *) &s_addr, sizeof(s_addr)) < 0){ 
        perror("- bind error\n");
        exit(1);
    }
    printf("+ bind to port number: %d\n", port);

    if(listen(server_socket, BACKLOG) < 0){ 
        perror("- listening error, can't hear something\n");
        exit(1);
    }
    printf("Listening...\n");

    while(1){
        c_addrsize = sizeof(c_addr);
        client_socket = accept(server_socket, (struct sockaddr*)&c_addr, &c_addrsize);
        
        if(client_socket > 0){
            printf("+ Client connected\n");
        }else {
            printf("- No Client connected\n");
            sleep(1);
            continue;
        }

        ssize_t bytesRead = recv(client_socket, &received_packet, sizeof(received_packet), 0);
        if( bytesRead <= 0 ){
            perror("- error receiving data from client\n");
            continue;
        }
        test[bytesRead] = '\0';
        printf("\n ----- Client -----\n");
        printf("s%d > %s\n",received_packet.sNummer, received_packet.text);

        printf("\n ----- response -----\n");
        printf("text: ");
        scanf("%s",response_packet.text);

        send(client_socket, &response_packet, sizeof(response_packet), 0);

        close(client_socket);
        printf("\n+ Client disconnected\n");
    }

    return 0;
}

最后是packet.h。这个数据包是我作业的一部分。它必须从客户端发送到服务器并返回。

#ifndef PACKET_H
#define PACKET_H

#include <stdint.h>

struct packet {
    char text[1024];
    uint32_t sNummer;
};

#endif
c sockets tcp ipv6
1个回答
0
投票

代码看起来没有什么问题。只需确保您使用的是正确的 ipv6 地址即可。 在服务器上运行

ip address
ifconfig
如果是
ip address
输出将是这样的

1: lo:
    ...
2: eth0:
    link/ether ...
    inet <IPv4> brd ... scope ...
      ...
    inet6 <IPv6> scope ...
      ...

使用 ipv4 或 ipv6(两者都适用于您的代码)。 例如:我的 ipv4:

192.168.0.105/24
(ipv6 需要
/24
部分) 你的可能会类似

确保两台计算机连接到同一网络并且防火墙不会导致任何问题。尝试使用

sudo ufw disable
禁用防火墙。

没有。 IP 地址后面不需要写“%eth0”。

© www.soinside.com 2019 - 2024. All rights reserved.