2013-08-02 54 views
2

这是简单的客户端 - 服务器聊天程序。此代码在网络上连接的计算机上工作正常,如何修改它以便它可以通过Internet在计算机之间进行连接。在gethostbyname()中使用服务器的公共IP无法使用。如何使用套接字编程在C中通过互联网连接两台计算机?

//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; 
} 
+2

您是否在要连接的路由器上配置了端口转发? –

+0

你们是在NAT路由器后面吗?你有没有转发适当的端口? –

+1

你确定这不是防火墙的问题吗? –

回答

3

根据您提供的信息,我认为不可能为您提出的问题提供解决方案。你已经说过,当两台计算机位于同一个本地网络上时,你的代码可以工作,所以代码(这是的,有问题)至少可以很好地从客户端连接到服务器。

如果(如所建立的)代码起作用,那么客户机和服务器是否在同一个网络或单独的网络上应该没有关系,只要有路由,路径,两者之间的连接网络。因此,如果客户端无法连接到服务器,结论就是这条路径丢失了。但是,缺少的路径并不是我们可以为您排除故障的问题:可能是“我的”Windows防火墙“阻止了此应用程序”,它可能是“我的ISP(或其他人的ISP)阻止了此端口,这可能是“另一家伙的服务条款包括一个”无服务器“条款,他们通过阻止所有端口强制执行”,它甚至可能是“我的ISP正在与其他人的ISP取得联系并赢得' t发送数据包给他们“

然而,由于你已经去发布这个代码的所有麻烦,并且我已经去了(a)阅读它的麻烦,和(b)写一个响应,我已经决定在你的代码中包含一些我在看到的问题上的评论。请注意,这是保证而不是是一个详尽的列表。

在Client.c:

  • 你打电话memset(),和铸造的第一个参数char *memset()函数被定义为将void *作为第一个参数。既然你已经#include <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以获取更多信息。
    • 根据POSIX.1-2004,“”传递数字地址字符串时,gethostbyname()的行为未指定“。 gethostbyname()函数期望传递一个实际的主机名,对于IP地址有gethostbyaddr()。 (或者当然是getaddrinfo()
  • 您正在使用gets()函数。 gets()函数在C99中已弃用,在POSIX.1-2008中标记为Obsolete,并从C11中排除,因为由于没有任何限制输入大小的原因,它基本上是不安全的。一般推荐的替代方案是fgets(),请注意,与gets()不同,fgets()函数不会丢弃\n字符。

在Server.c:

  • 你还在铸造的第一个参数memset()char *,这仍然是不必要的和错误的,
  • 你还在使用gets()功能,仍然是固有的问题,
  • 你在做write(client_connected, message, sizeof(message));。每个来自服务器的响应都是100个字节长,垃圾字节写在响应字符串后面。改为使用strlen(message)+1

在两种:

  • 你的消息是由用户输入的字符串,但是,当客户端发送消息时,它不包括终端空字节。收件人只能读取发件人写入的内容,因此它不会收到终端空字节......这只是一个问题,因为接收代码假定它收到的是有效的字符串。确保你的消息在字符串末尾包含null,指定的消息大小比strlen(message)多一个。
0

经过我的研究后,我想出了这个答案。如果你想通过互联网连接设备,你需要一个具有唯一IP地址的服务器,例如你可以在线购买一台设备。当您尝试在家庭网络中创建设备作为服务器时,您需要提供全局IP地址,并且由于ISP使用路由器通过网络为您提供了许多设备共享的单个公用IP,因此无法创建ServerSocket通过许多设备共享的家庭网络

0

您不能仅通过全局IP连接到设备,但是如果您打开端口,则只能向服务器端口转发,然后才能创建套接字。

相关问题