How to connect two computers over internet using socket programming in C?
Asked Answered
R

4

6

This is simple Client-Server chat program.This code is working fine on computers connected on Network, how to modify it such that it can connect between computers over the Internet. Using Public IP of the server in gethostbyname() isn't working.

//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;
}
Reverence answered 2/8, 2013 at 15:50 Comment(5)
have you configured port forwarding on the router you want to connect to?Monostrophe
Are either of you behind NAT routers? Have you forwarded the appropriate ports?Kastner
You sure it's not an issue with firewalls?Louisiana
Besides the possible firewall issues, when a system call like connect fails, then checking errno (and printing it out with e.g. perror) is usually a good idea.Warmth
Always a good idea. Mandatory, in fact.Eisteddfod
L
7

Based on the information you've given, I don't think it's possible to provide a solution to the question you're asking. You've stated that your code works when the two computers are on the same local network, so clearly the code (which, yes, has issues) works at least well enough to connect from client to server.

If (as is established,) the code works, then it shouldn't matter whether the client and server are on the same network or separate networks, so long as there's a route, a path, a connection between the two networks. Therefore, if the client can't connect to the server, the conclusion is that this path is missing. The path being missing, however, is not a problem we can troubleshoot for you: It might be "my 'Windows Firewall' is blocking this app", it might be "my ISP (or the other guy's ISP) is blocking this port", it might be "The other guy's terms of service with his ISP includes a "no servers" clause which they enforce by blocking all ports", it might even be "my ISP is on the outs with the other guy's ISP and won't route packets to them anymore".

However, since you've gone to all the trouble of posting this code, and I've gone to the trouble of (a) reading it, and (b) writing a response, I've decided to include some commentary on issues I see in your code. Note that this is guaranteed not to be an exhaustive list.

In Client.c:

  • You're calling memset(), and casting the first argument to char *. The memset() function is defined to take a void * as the first argument. Since you've #included <string.h> you have a correct prototype in scope, so whatever you pass to it will be converted to a void * automatically. The cast is therefore both incorrect and pointless.
  • You're calling gethostbyname(), and the string you're passing is an IPv4 address.
  • The gethostbyname() and gethostbyaddr() functions were deprecated in POSIX.1-2004 and were excluded from POSIX.1-2008. They are replaced by getaddrinfo() (and getnameinfo()), and I refer you to System Calls/getaddrinfo() section of Beej's Guide to Network Programming for further information.
  • According to POSIX.1-2004, "the behavior of gethostbyname() when passed a numeric address string is unspecified". The gethostbyname() function expects to be passed an actual hostname, for IP addresses there's gethostbyaddr(). (Or getaddrinfo() now, of course.)
  • You're using the gets() function. The gets() function was deprecated in C99, marked as Obsolete in POSIX.1-2008, and excluded from C11, because it is fundamentally unsafe due to not having any way of limiting input size. The generally recommended alternative is fgets(), note that unlike gets(), the fgets() function doesn't discard the \n character.

In Server.c:

  • You're still casting the first argument to memset() to char *, which is still unnecessary and wrong,
  • You're still using the gets() function, which is still inherently problematic,
  • You're doing write(client_connected, message, sizeof(message));. Every response from the server will be the full 100 bytes long, with garbage bytes being written after the response string. Use strlen(message)+1 instead.

In both:

  • Your message is a string that was input by the user, but when the client sends the message, it doesn't include the terminal null byte. The recipient can only read what the sender writes, so it isn't receiving a terminal null byte... which is only a problem because the receiving code assumes that what it received is a valid string. Make sure your messages include the null at the end of the string, by having the specified message size be one more than strlen(message).
Liman answered 4/8, 2013 at 6:29 Comment(0)
S
2

Well after my research I came up with this answer. If you want to connect Devices over Internet you need to have a Server having a unique IP Address Eg you could buy one online. When you try to create a device in your home network as Server you need to provide the Global IP Address and since the ISP provides you with a single Public IP shared by a lot of devices over the Network using a router, you cant create a ServerSocket over a Home network shared by many Devices

Saideman answered 2/1, 2015 at 8:41 Comment(0)
M
0

You can't connect to a device only by the global IP but if you open a port, port forward, only for the server then the socket can be made.

Minivet answered 14/11, 2016 at 19:29 Comment(0)
A
0

You probably need to do port forwarding using ngrok or any other port forwarding software.

ngrok will give a url for your client to connect to and any packet sent to that url will be forwarded to your server.

that way you can sent packets between computers that are on different networks

Alleviation answered 19/3 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.