这是简单的客户端 - 服务器聊天程序。此代码在网络上连接的计算机上运行良好,如何修改它以便它可以通过Internet连接到计算机。在gethostbyname()
中使用服务器的公共IP无效。
//Client.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(void)
{
int clientSocket; /* Socket Decriptor for Client */
struct sockaddr_in server_addr;
struct hostent *ptrh;
char message[100];
char received[100];
int n = 0;
clientSocket=socket(AF_INET, SOCK_STREAM, 0);
memset((char*)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(10000);
/* bind(clientSocket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); */
ptrh=gethostbyname("110.172.156.2");
memcpy(&server_addr.sin_addr,ptrh->h_addr,ptrh->h_length);
if( -1 == (connect(clientSocket, (struct sockaddr*)&server_addr, sizeof(server_addr))))
{ printf("\nServer Not Ready !!\n"); exit(1); }
while(1)
{
printf("\nUser:-");
// memset(message, '\0', 10);
gets(message);
n = write(clientSocket, message, strlen(message)+1);
if( (strcmp(message,"q") == 0 ) || (strcmp(message,"Q") == 0 ))
{
printf("Wrong place...Socket Closed\n");
close(clientSocket);
break;
}
//printf("Write:<%u>\n", n);
read(clientSocket, received, sizeof(received));
if( (strcmp(received,"q") == 0 ) || (strcmp(received,"Q") == 0 ))
{
printf("Wrong place...Socket Closed\n");
close(clientSocket);
break;
}
else
printf("Server:- %s\n", received);
}
return 0;
}
//Server.c
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<netdb.h>
int main(void)
{
int serverSocket,client_connected,len;
struct sockaddr_in client_addr,server_addr;
struct hostent *ptrh;
int n=0;
char message[100],received[100];
serverSocket=socket(AF_INET, SOCK_STREAM, 0);
memset((char*)&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(10000);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(serverSocket,
(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
printf("Bind Failure\n");
else
printf("Bind Success:<%u>\n", serverSocket);
while(1)
{
listen(serverSocket,5);
len=sizeof(struct sockaddr_in);
client_connected=accept(serverSocket,
(struct sockaddr*)&client_addr,&len);
if (-1 != client_connected)
printf("Connection accepted:<%u>\n", client_connected);
while(1)
{
n = read(client_connected, received, sizeof(received));
if( (strcmp(received,"q") == 0 ) || (strcmp(received,"Q") == 0 ))
{
printf("Wrong place...Socket Closed of Client\n");
close(client_connected);
break;
}
else{
printf("\nUser:-%s", received);}
printf("\nServer:-");
// memset(message, '\0', 10);
gets(message);
write(client_connected, message, sizeof(message));
if( (strcmp(message,"q") == 0 ) || (strcmp(message,"Q") == 0 ))
{
printf("Wrong place...Socket Closed of Client\n");
close(client_connected);
break;
}
}
}
close(serverSocket); printf("\nServer Socket Closed !!\n");
return 0;
}
答案 0 :(得分:3)
根据您提供的信息,我认为不可能为您提出的问题提供解决方案。您已经说过,当两台计算机位于同一本地网络上时,您的代码就可以工作,所以很明显代码(有问题,有问题)至少能够很好地连接客户端到服务器。
如果(如已建立的话)代码有效,那么无论客户端和服务器是在同一网络还是单独的网络上,只要路由,路径,两个网络之间的连接都无关紧要。因此,如果客户端无法连接到服务器,则结论是缺少此路径。然而,缺少的路径不是我们可以为您解决的问题:可能是“我的'Windows防火墙'正在阻止此应用程序”,它可能是“我的ISP(或其他人的ISP)阻止此端口,它可能是“他的ISP的另一个人的服务条款包括一个”无服务器“条款,他们通过阻止所有端口强制执行”,它甚至可能是“我的ISP与其他人一起出局家伙的ISP并且不再将数据包路由给他们了。“
然而,既然你已经发布了这个代码的麻烦,我已经遇到了麻烦(a)阅读它,以及(b)写了一个回复,我决定加入一些评论我在你的代码中看到的问题。请注意,这保证不是一个详尽的列表。
在Client.c中:
memset()
,并将第一个参数转换为char *
。 memset()
函数定义为将void *
作为第一个参数。由于您已经#included <string.h>
,因此您在范围内拥有正确的原型,因此无论您传递给它的是什么,都会自动转换为void *
。因此,演员阵容既不正确也毫无意义。gethostbyname()
,您传递的字符串是IPv4地址。
gethostbyname()
和gethostbyaddr()
函数在POSIX.1-2004中已弃用,并已从POSIX.1-2008中排除。它们被getaddrinfo()
(和getnameinfo()
)取代,我会将您推荐给Section 5.1 of Beej's Guide to Network Programming
以获取更多信息。gethostbyname()
函数传递实际主机名,对于IP地址gethostbyaddr()
。 (当然,或者getaddrinfo()
。)gets()
功能。 {C}中已弃用gets()
函数,在POSIX.1-2008中标记为已废弃,并且从C11中排除,因为由于没有任何限制输入大小的方式,它基本上是不安全的。通常建议的替代方案为fgets()
,请注意,与gets()
不同,fgets()
函数不会丢弃\n
字符。在Server.c中:
memset()
转换char *
的第一个参数,这仍然是不必要和错误的,gets()
功能,这仍然存在问题,write(client_connected, message, sizeof(message));
。服务器的每个响应都是100个字节长,在响应字符串后写入垃圾字节。请改用strlen(message)+1
。两者:
strlen(message)
,确保您的邮件在字符串末尾包含null。答案 1 :(得分:1)
在我的研究之后,我想出了这个答案。如果要通过Internet连接设备,则需要具有唯一IP地址的服务器,例如,您可以在线购买。当您尝试在家庭网络中创建设备作为服务器时,您需要提供全局IP地址,并且由于ISP使用路由器通过网络为您提供了许多设备共享的单个公共IP,因此您无法创建ServerSocket通过许多设备共享的家庭网络
答案 2 :(得分:0)
您无法仅通过全局IP连接到设备,但是如果您打开一个端口,只能为服务器端口转发,那么就可以建立套接字。