繁体   English   中英

UNIX套接字编程:获取C客户端连接到Python服务器的问题

[英]UNIX Socket Programming: Issues Getting a C Client to Connect to a Python Server

我正在尝试让C客户端连接到UNIX / Linux中的Python服务器。 但是,看来我的C客户端无法连接到Python服务器。 我尝试在localhost上运行,但这似乎不起作用。 将主机名硬编码到服务器和客户端中(分别为“ 127.0.0.1”)也不起作用。

这是Python服务器的代码:

import socket
import sys

HOST = "127.0.0.1"
PORT = 8888

print("creating socket...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print("binding socket...")
try:
    s.bind((HOST, PORT))
except socket.error as err:
    print("error binding socket, {}, {}".format(err[0], err[1]))
print("successfully bound socket")

s.listen(1)
print("now listening on {}:{}".format(HOST, PORT))

while True:
    conn, addr = s.accept()
    conn.sendall(str.encode("testing"))
    #conn.close()

s.close()

...这是C客户端的代码:

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

int main(int argc, char** argv) {
    if (argc != 3) {
        printf("usage: client [HOSTNAME] [PORT]\n");
        return 0;
    }

    const char *hostname = argv[1];
    int port = atoi(argv[2]);

    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in saddr;

    memset(recvBuff, '0', sizeof(recvBuff));
    if ( sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0 ) {
        fprintf(stderr, "error: could not create socket\n");
        return 1;
    }

    saddr.sin_family = AF_INET;
    saddr.sin_port   = htons(port);
    saddr.sin_addr.s_addr = htonl(hostname);

    if ( connect(sockfd, (struct sockaddr_in*)&saddr, sizeof(saddr)) < 0 ) {
        fprintf(stderr, "error: could not connect to %s:%i\n", hostname, port);
        return 1;
    }

    while ( n = read(sockfd, recvBuff, sizeof(recvBuff) - 1) > 0 ) {
        recvBuff[n] = 0;
        if ( fputs(recvBuff, stdout) == "EOF" ) {
            fprintf(stderr, "error: fputs\n");
        }

        printf("\n");
    }

    return 0;
}

有趣的是,我仍然可以通过其他方式(例如telnet)或通过此Python编码的客户端连接到Python服务器:

import socket
import sys

HOST = "localhost"
PORT = 8888

print("creating socket")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print("attempting to connect to host")
try:
    s.connect((HOST, PORT))
except socket.error as err:
    print("error: could not connect to host, {}, {}".format(err[0], err[1]))
    sys.exit()

print("successfully connected to host")

data = s.recv(1024)
s.close()

print("The server responded with: {}".format(data))

我认为这是一个客户端问题,因为连接到服务器的其他方法似乎工作正常。 如果是这种情况,我将如何修复C代码以正确连接? 如果不是这种情况,这可能是与我的网络有关的问题吗? 我尝试同时在Arch VM和学校的IT服务器中运行,并且都得到了相同的结果。

您的C客户端错误地将地址设置为(尝试连接)。 实际上,鉴于变量hostname是指向程序参数之一的char * ,这是完全错误的:

saddr.sin_addr.s_addr = htonl(hostname);

您的编译器应发出有关它的警告。 如果不是,则调高警告级别或获得更好的编译器。 htonl()需要一个32位无符号整数作为其参数。 可以将指针转换为该类型(尽管不是强制转换,除了作为扩展名),但是可以转换指针本身 ,而不是指针指向的数据。

您需要提供的字符串形式的地址转换成数字形式,并分配给您的套接字地址。 如果您愿意依靠“主机名”来将其格式化为点分四进制的IPv4地址,则可以执行以下操作:

int result = inet_pton(AF_INET, hostname, &saddr.sin_addr);

不要忽略检查返回值,并且要注意它采用了一种不同寻常的约定:如果转换成功,您正在寻找返回的值是1(不是0)。

如果要接受域名以及点分四进制的地址,则需要使用解析器来帮助您根据程序参数选择合适的目标地址。 getaddrinfo()函数是您最好的选择,但是仔细阅读(链接的)文档,因为这有一些潜在的陷阱。

如果您查看了htonl的手册,它将显示htonl(uint32_t hostlong);

您正在传递一个字符串作为参数,希望将其转换为正确的uint32格式。 那不会发生。

您可以使用例如

hostinfo = gethostbyname (hostname);
saddr->sin_addr = *(struct in_addr *) hostinfo->h_addr;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM