3

I am trying to write a program that sends basic text files from one computer to another using C++ over the internet (or a LAN). I was looking into Winsock but everything that I read made it seem like it was only for communication between a server and a client. I am not sure if this is what I am trying to do or if I am looking at a different problem.

EDIT: Thanks for the great answers guys. I kind of feel bad for having to choose a best one out of the lot.

BlueMeanie
  • 148
  • 1
  • 1
  • 10

6 Answers6

2

A client-server architecture should be fine for sending files. The "server" is simply the program that starts first, and waits for the other (the client) to connect to it. Past there, there's not a lot of difference between the two. In a lot of cases, it's easiest to write the code so it automatically attempts to contact a server, and if it can't find one, it sets itself up as the server.

Also note that making things work across the internet with (particularly) NAT routers involved can make the code a little trickier. It's not all that tough if you pre-configure the firewall to allow the connection(s), but otherwise you typically end up using UPnP to establish the connection through the firewall. That can easily double the work compared to doing the job locally without NAT involved.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

Here is an example of how to copy/transfer files using C/C++ in Linux.The server listens in port 8080. The client transmits a filename. The server receives the filename, open the file and sends its contents to the client. I intentionally used odd or small buffer sizes for illustrative purposes.

The server.c file:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>

int main (int argc,char *argv[])
{
    struct sockaddr_in p;
    struct sockaddr_in q;
    int z,s,t,x,n,b = sizeof(q);
    char buf[23];
    int fd;

    s = socket(AF_INET,SOCK_STREAM,0);

    bzero (&p,sizeof(p));
    p.sin_family = AF_INET;
    p.sin_addr.s_addr = INADDR_ANY;
    p.sin_port = htons(8080);

    bind (s,(struct sockaddr*)&p,sizeof(p));
    listen(s,13);

    while (1) {
        t = accept (s,(struct sockaddr*)&q, &b);
        n = read(t,buf,23);
        buf[n] = 0;
        printf("%s sent: ",buf);
        fd = open (buf,O_RDONLY);
        z = lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);
        x = 0;
        do {
            n = read (fd,buf,23);
            write (t,buf,n);
            x += n;
        } while (x < z);
        printf("%d/%d\n",x,z);
        close(fd);
        close(t);
    }
}

The client.c file:

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>

void main (int argc, char *argv[]) 
{
    int ret;
    char buf[5];
    int s,n,fd;
    struct sockaddr_in p;
    struct hostent *h;
    char *str = argv[1];

    fd = open (str,O_CREAT | O_WRONLY,S_IRUSR|S_IWUSR);
    h = gethostbyname("127.0.0.1");

    bzero(&p,sizeof(p));
    p.sin_family = AF_INET;
    p.sin_addr.s_addr = htonl(INADDR_ANY);
    p.sin_addr.s_addr = ((struct in_addr*)(h->h_addr))->s_addr;
    p.sin_port = htons(8080);

    s = socket (AF_INET,SOCK_STREAM,0);
    connect (s,(void*)&p,sizeof(p));
    n = write (s,str,strlen(str));
    int idx = 0;
    do {
        n = read (s,buf,5);
        idx += n;
        printf(".");
        fflush(stdout);
        write (fd,buf,n);
    } while (n > 0);
    close (fd);
    close (s);
}

To compile:

  1. Open terminal
  2. gcc -o server server.c
  3. gcc -o client client.c

Run the server as ./server. And then to copy rngoidiot.txt, run the client as ./client rngoidiot.txt and the file will be copied using TCP/IP. Simple combination ;-)

daparic
  • 3,794
  • 2
  • 36
  • 38
1

In short: Yes, sockets are the way to go.

"Server" and "client" in the sockets sense are generic terms - your system is running a variety of both at any given time. For example, your web browser operates as an HTTP client (where HTTP is a text-bounded mostly-synchronous protocol running over TCP/IP); Windows file sharing and remote desktop are "servers" that other systems connect into.

The distinction between server and client in the sockets sense (really in the TCP/IP sense) is that a "server" socket listens for incoming connections from remote systems (refer to MSDN or man pages on bind(), listen(), accept()) whereas a "client" socket creates outgoing connections to remote systems (connect()).

Beware that sockets programming can be a bit tricky. What you describe is a good learning exercise, but if you're trying to get something done quickly, you might look at existing tools such as netcat.

lyngvi
  • 1,312
  • 12
  • 19
0

it seem like it was only for communication between a server and a client

So what? Make one computer (that is about to receive the file) the server. On that computer create a socket and make it listen for a connection on a port. Once a connection arrives, get the data according so some defined structure (see below)

The sender computer (the client, sort of) will connect to the other computer, and it knows the IP address and the port no. (The two must be known to the client for the connection). Once connection is made, it will send the data as a sequence of bytes to the server.

The structure:

The two computers that are communicating here must have a well defined structure that is known and accepted by both. The simplest structure will be:

|Length-Of-Data | Data ......  |
 <-- 4 bytes---> <-- n bytes-->

Read the n from the first 4 bytes. The 4 bytes (n) here represent the length of the data and could be different, its your definition.

You could have many more 'fields' (depending on the functionality) for filename, file-type etc..

UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
0

If you want to send files over internet, you have to use sockets, or better yet other high level library implemented with sockets.

In the TCP sockets terminology, there is no big difference between client and server: the communications is two way. The only difference is in who is listening for incoming connections (bind, listen, accept), and who is initiating the connection (open).

You mentioned Winsock, it means that you are working on Windows. Take a look into the Windows API, probably you can find some high level library that handles the file transfer (like a FTP or HTTP library).

Maybe doesn't fit your requirements, but you can also use a shared folder for a LAN and a folder synchronized by Dropbox for the Internet... then just use standard IO.

Diego
  • 4,353
  • 1
  • 24
  • 22
0

Speaking generally, any file transfer requires some sort of server/client connection. One computer needs to initiate a connection, and the other computer needs to be listening for the connection at the other end, and then take the actions it is instructed to by the first computer.

While you can certainly roll out your own client and server software using sockets, depending on what sorts of computers you want to transfer files between, it might make the most sense to leverage some existing client/server protocol. Some of the more popular possibilities include ssh, http, or ftp. I think C/C++ libraries should exist for all of these protocols.

Without more information I would be inclined to use ssh. Installing an ssh server shouldn't be too hard, so you'll only have to write the client software, and I think some pretty good open source libraries exist for that.

EDIT: libssh looks pretty good!

Julian
  • 2,483
  • 20
  • 20