Well... You probably don't want to delve into raw Ethernet. What you want to
do is implement some sort of Tcp/Ip data transfer and let the kernel(s) sweat
the details.
Tcp/Ip uses a client / server model: one side is the "server" and the other is
the "client". The server is a little more complicated than the client.
To implement a "server" process, you need to creating a socket, bind it to a
port [number] and then listen on it and when someone connects to the port (the
client), you then start communicating.
In C you would use these functions:
socket() -- create a socket
bind() -- bind it to an address & port
listen() -- listen for connections
accept() -- accept a connection to the client
Then:
read() and write() to actually transfer data, then close() when done.
Minimial C program would look something like this:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#define ERRORCHECK(funcall,message) \
if ((funcall) < 0) { \
int err = errno; \
perror(message); \
exit(err); \
}
#define PORT 10000 /* Port we will be listening on. */
int do_dataTransfer(int connection,struct sockaddr_in *fromAddress);
int main(int argc, char *argv[])
{
int listenSock, connectSock, pstatus;
struct sockaddr_in my_addr, peer_addr;
socklen_t peer_addr_size;
struct pollfd ufd;
/* Create a socket */
listenSock = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK,0);
ERRORCHECK(listenSock,"Failed to create socket")
memset(&my_addr,0,sizeof(my_addr)); /* clear out the address */
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* listen on all addresses */
my_addr.sin_port = htons(PORT);
my_addr.sin_family = AF_INET;
/* Bind the address to a port */
ERRORCHECK(bind(listenSock,(const struct sockaddr*)&my_addr,sizeof(my_addr)))
/* Listen for clients */
ERRORCHECK(listen(listenSock,1) /* backlog of one: only one client at a time */
/* Check to see if anyone wants to talk to us */
while (1) {
ufd.fd = listenSock;
ufd.events = POLLIN;
pstatus = poll(&ufd,1,10);
ERRORCHECK(pstatus,"Poll failed");
if (pstatus > 0) {
/* Someone wants to talk, connect to his socket */
connectSock = accept(listenSock,(struct sockaddr*)&peer_addr,&peer_addr_size);
ERRORCHECK(connectSock,"Accept failed");
if (connectSock > 0) {
/* We are connected. Now we can talk to each other. */
do_dataTransfer(connectSock,&peer_addr);
}
}
usleep(50000); /* sleep 50 ms */
}
}
The client program would use socket() to create the socket, then connect() to
connect it to a server. And then read() and write() to transfer data and
finally close() to close the connection.
On most Linux machines, there are man pages for all of these functions (in
section 2). There are probably zillions of example programs out on the
Internet as well.