当前位置: 首页 > news >正文

Python客户端和C服务器之间的连接问题及其解决方案

Python 客户端与 C 服务器之间的连接问题通常涉及到通信协议、数据格式、传输方式等方面。通常,Python 客户端和 C 服务器可以通过 套接字(socket) 来进行通信,这也是最常见的实现方式。

在这里插入图片描述

1、问题背景

  • 有一个用Python编写的客户端想要连接到一个用C编写的回声服务器。
  • 客户端可以成功连接到一个用Python编写的服务器,但无法连接到C服务器。
  • 客户端代码使用了Python的socket模块,服务器代码使用了C语言的套接字编程。

2、解决方案

  • 检查C服务器的端口是否正确。
  • 确保C服务器正在运行。
  • 检查客户端和服务器是否在同一个网络上。
  • 尝试使用不同的端口。
  • 检查防火墙或其他网络设置是否阻止了连接。

以下是服务器代码的改进版本,使用bind()函数将服务器绑定到一个特定的端口,并使用listen()函数监听传入的连接:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>

#ifndef AF_INET
#define AF_INET 2
#endif

#ifndef SOCK_DGRAM
#define SOCK_DGRAM 2
#endif

#ifndef INADDR_ANY
#define INADDR_ANY 0
#endif

#ifndef IP_DONTFRAG
#define IP_DONTFRAG     67
#endif

#define BUFFER_SIZE 1024

#define ECHO_PORT_UDP 10000
#define ECHO_PORT_TCP 11000

int main(int argc, char *argv[]) {
    int echo_socket = 0;
    int echo_socket_child = 0; // for TCP
    struct sockaddr_in server;
    struct sockaddr_in client;
    struct hostent *hostp; // client host info
    struct sockaddr_in clientaddr; // client addr
    char *hostaddrp; // dotted decimal host addr string
    char buffer[BUFFER_SIZE];
    unsigned int clientlen = 0;
    unsigned int serverlen = 0;
    int received = 0;
    int port = 0;
    char *endptr;
    int optval = 1;
    int msg_byte_size = 0;


// Parameters check
    if (argc == 2) {
        port = strtol(argv[1], &endptr, 0);
        if ((*endptr) || ((port != ECHO_PORT_UDP) && (port != ECHO_PORT_TCP)))  {
        printf("EchoServer: Invalid port number.\n Use port %d for UDP, port %d for TCP.\n", ECHO_PORT_UDP, ECHO_PORT_TCP);
            return -1;
        }
        else {
            if (port == ECHO_PORT_UDP) {
                printf("EchoServer: Running UDP on port %d.\n", port);
            }
            if (port == ECHO_PORT_TCP) {
                printf("EchoServer: Running TCP on port %d.\n", port);
            }
        }
    }
    else {
        printf("EchoServer: Invalid arguments.\n");
        return -1;
    }


// Opening UDP socket
    if (port == ECHO_PORT_UDP) {
        if ((echo_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            printf("EchoServer: Failed opening socket");
            return -1;
        }

    }
    if (port == ECHO_PORT_TCP) {
        if ((echo_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            printf("EchoServer: Failed opening socket");
            return -1;
        }

        // setsockopt: Handy debugging trick that lets  us rerun the server immediately after we kill it; otherwise we have to wait about 20 secs.
        // Eliminates "ERROR on binding: Address already in use" error.
        setsockopt(echo_socket, SOL_SOCKET, SO_REUSEADDR,(const void *)&optval , sizeof(int));

    }

// Construct the server sockaddr_in structure
    memset(&server, 0, sizeof(server));             /* Clear struct */
    server.sin_family = AF_INET;                    /* Internet/IP */
    server.sin_addr.s_addr = htonl(INADDR_ANY);     /* Any IP address */
    server.sin_port = htons(atol(argv[1]));         /* server port */

// Bind the socket
    serverlen = sizeof(server);
    if (bind(echo_socket, (struct sockaddr *) &server, serverlen) < 0) {
        printf("EchoServer: Failed binding socket");
        return -1;
}    


// Listen for connections for TCP
if (port == ECHO_PORT_TCP) {
    if (listen(echo_socket, 5) < 0) {
        printf("EchoServer: Failed listening for connections");
        return -1;
    }
}


// Wait for a datagram until cancelled
if (port == ECHO_PORT_UDP) {
    while (1) {
        /* Receive a message from the client */
        clientlen = sizeof(client);
        if ((received = recvfrom(echo_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &clientlen)) < 0) {

            printf("EchoServer: Failed receiving datagram");
            return -1;
        }
        printf("Client datagram received from: %s\n", inet_ntoa(client.sin_addr));
        /* Send the message back to client */
        if (sendto(echo_socket, buffer, received, 0, (struct sockaddr *) &client, sizeof(client)) != received) {
            printf("Mismatch in number of echoed bytes");
            return -1;
        }
    }
}

// Wait for a connection until cancelled
if (port == ECHO_PORT_TCP) {
    while (1) {
        echo_socket_child = accept(echo_socket, (struct sockaddr *) &client, &clientlen);
        if (echo_socket_child < 0) {
            printf("ERROR on accept");
            break;
        }

        // gethostbyaddr: determine who sent the message
        hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        if (hostp == NULL) {
            printf("ERROR on gethostbyaddr");
            break;
        }
        hostaddrp = inet_ntoa(clientaddr.sin_addr);
        if (hostaddrp == NULL) {
            printf("ERROR on inet_ntoa\n");
            break;
        }
        printf("server established connection with %s \n", hostaddrp);

        // read: read input string from the client
        bzero(buffer, BUFFER_SIZE);
        msg_byte_size = read(echo_socket_child, buffer, BUFFER_SIZE);
        if (msg_byte_size < 0) {
            printf("ERROR reading from socket");
            break;
        }
        printf("server received %d bytes: %s", msg_byte_size, buffer);

        // write: echo the input string back to the client
        msg_byte_size = write(echo_socket_child, buffer, strlen(buffer));
        if (msg_byte_size < 0) {
            printf("ERROR writing to socket");
            break;
        }
    } // endof while(1)
    close(echo_socket_child);
    return -1;
}
return 0;

}

另外,还要确保客户端和服务器使用相同的协议(TCP或UDP)进行通信。

Python 客户端与 C 服务器之间的连接问题可能会涉及多方面的因素。常见的解决方案包括:

  • 确保协议和数据格式的一致性。
  • 处理好网络连接、超时、缓冲区大小等问题。
  • 合理使用多线程/多进程来处理并发连接。
  • 配置好适当的超时、字符集编码等。

通过以上方法,可以确保 Python 客户端和 C 服务器之间的连接能够正常稳定地进行。

相关文章:

  • 在 Windows 系统中如何快速进入安全模式的两种方法
  • Django中select_related 的作用
  • 51单片机看门狗系统
  • 读取本地excel删除第一行,并生成List数组
  • 贪心算法与动态规划的区别
  • GPT-4o微调SFT及强化学习DPO数据集构建
  • 装饰器模式 + 责任链模式:动态增强的流水线处理艺术
  • Modbus TCP协议
  • 【第2章:神经网络基础与实现——2.1 前馈神经网络的结构与工作原理】
  • 亚远景-ASPICE 4.0 与 AI 驱动的汽车软件开发:未来趋势与挑战
  • 力扣第一题 哈希解法 O(n)时间复杂度
  • zyNo.23
  • springcloud集成gateway
  • 将Sqlite3数据库挂在内存上处理
  • 【STM32系列】利用MATLAB配合ARM-DSP库设计IIR数字滤波器(保姆级教程)
  • GPU并行计算的深度学习pyTorch环境搭建
  • WinForm 防破解、反编译设计文档
  • Git 与 Git常用命令
  • SpringBoot
  • 麒麟操作系统-Redis5二进制安装
  • 河南省委常委会会议:坚持以案为鉴,深刻汲取教训
  • “老中青少”四代同堂,季春艳携锡剧《玲珑女》冲击梅花奖
  • 秘鲁总理辞职
  • 白玉兰奖征片综述丨动画的IP生命力
  • 这个“超强致癌细菌”,宝宝感染率高达40%,预防却很简单
  • 广西壮族自治区党委政法委副书记李文博接受审查调查