Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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;
}
like image 595
dushyantashu Avatar asked Aug 02 '13 15:08

dushyantashu


People also ask

What is socket () bind () listen () accept () and connect ()?

Create a socket with the socket() function; Bind the socket to an address using the bind() function; Listen for connections with the listen() function; Accept a connection with the accept() function system call. This call typically blocks until a client connects with the server.

Can socket programming be done in C?

It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. At this point, the connection is established between client and server, and they are ready to transfer data.

What does socket () do in C?

The socket() function shall create an unbound socket in a communications domain, and return a file descriptor that can be used in later function calls that operate on sockets. The socket() function takes the following arguments: domain. Specifies the communications domain in which a socket is to be created.


2 Answers

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).
like image 107
This isn't my real name Avatar answered Sep 21 '22 11:09

This isn't my real name


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

like image 43
Kartik Gupta Avatar answered Sep 18 '22 11:09

Kartik Gupta