[英]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.