这是一个简单的客户端-服务器聊天程序。此代码在连接到网络的计算机上运行良好,如何修改它以便它可以通过 Internet 在计算机之间连接。使用 gethostbyname()
中服务器的公共(public) 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;
}
最佳答案
根据您提供的信息,我认为无法为您提出的问题提供解决方案。您已经说过,当两台计算机在同一个本地网络上时,您的代码可以工作,所以很明显,代码(是的,有问题)至少可以很好地从客户端连接到服务器。
如果(如已确定的那样)代码有效,那么客户端和服务器是在同一个网络上还是在不同的网络上都无关紧要,只要两个网络之间存在路由、路径、连接即可。因此,如果客户端无法连接到服务器,则结论是缺少这条路径。但是,丢失的路径不是我们可以为您解决的问题:它可能是“我的‘Windows 防火墙’阻止了这个应用程序”,也可能是“我的 ISP(或其他人的 ISP)阻止了这个端口” ,可能是“对方与他的 ISP 的服务条款包括一个“无服务器”条款,他们通过阻止所有端口来强制执行该条款”,甚至可能是“我的 ISP 与对方的 ISP 不合,不会不再将数据包路由给他们”。
但是,由于您费尽心思发布此代码,而且我费尽心思(a)阅读它,(b)写回复,我决定包括一些关于我的问题的评论在您的代码中查看。请注意,这保证不是一个详尽的列表。
在 Client.c 中:
memset()
, 并将第一个参数转换为 char *
. memset()
函数定义为采用 void *
作为第一个论点。既然你已经#included <string.h>
你在范围内有一个正确的原型(prototype),所以你传递给它的任何东西都将转换为 void *
自动地。因此, Actor 阵容既不正确又毫无意义。 gethostbyname()
,并且您传递的字符串是 IPv4 地址。 gethostbyname()
和 gethostbyaddr()
函数在 POSIX.1-2004 中被弃用,并被排除在 POSIX.1-2008 之外。它们被 getaddrinfo()
取代(和 getnameinfo()
),我推荐你到 System Calls/getaddrinfo() section of Beej's Guide to Network Programming
了解更多信息。 gethostbyname()
函数需要传递一个实际的主机名,对于 IP 地址有 gethostbyaddr()
. (当然,现在是 getaddrinfo()
。)gets()
功能。 gets()
函数在 C99 中已弃用,在 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)
大一,确保您的消息在字符串末尾包含空值。 . 关于c - 如何使用 C 中的套接字编程通过 Internet 连接两台计算机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18021189/