This could be done with forking, but you'd need to remember that, aside from pre-existing files and sockets, every forked program becomes completely seperate. Variables changed in one won't be reflected in another.
Threads, on the other hand, share the same process and memory, running more or less "at the same time" thanks to multitasking. You can use the same variables, but this can cause strange synchronization problems unless you're careful to control access to these things with thread-control devices like semaphores and mutexes...
Imagine two threads doing a memcpy to one area of memory, one starts a memcpy and is interrupted, then the second one starts and finishes a memcpy to the same area of memory, then the first one finishes, leaving the memory half one thing and half the other. A mutex would make one wait for the other one. Threads are also more portable; both Windows and UNIX have threads, but Windows does not and will never have fork().
But this is a lot of stuff to learn simultaneously if these are all new concepts to you, and designs that have to be complete for them to work are really hard to build. Try simplifying it even further. Forget about the client/server objects for now and just hardcode the making and breaking of connections in main(), which in turn, would call communications functions that use these sockets without worrying about how to make or break them. Pseudocode:
// comm.h
// Including this more than once won't hurt
#ifndef __COMM_H__
#define __COMM_H__
// Lets include file work in C *and* C++
#ifdef __cplusplus
extern "C" {
#endif
int recieve_message(int fd, char *buf, int maxlen);
int send_message(int fd, const char *buf);
#ifdef __cplusplus
}
#endif
#endif/*__COMM_H__*/
// comm.c
#include "comm.h"
// Return of 0 means success, return <0 means error
int recieve_message(int fd, char *buf, int maxlen)
{
...
}
// Return of 0 means success, return <0 means error
int send_message(int fd, const char *buf)
{
...
}
// server.c
#include "comm.h"
int main()
{
char buf[512];
int serversock=open_server_socket();
int client=accept(serversock); // will block, so what?
recieve_message(client,buf,512);
fprintf(stderr,"%s\n",buf);
send_message(client,"hey guys alj af MY FACE IS A ROTTORN BANANA");
close(client);
close(serversock);
return(0);
}
// client.c
#include "comm.h"
int main()
{
char buf[512];
int server=connect_to_server("localhost");
send_message(server,"How is your face doing?");
recieve_message(server,buf,512);
fprintf(stderr,"%s\n",buf);
return(0);
}
$ gcc -c server.c client.c comm.c
$ gcc server.o comm.o -o server
$ gcc client.o comm.o -o client
$ ./server &
$ ./client &
...
Once you get the send/recieve functions working how you want them, then you can build a system to hold it all together. Don't get ahead of yourself. The right way to do this might not be apparent until you've actually done some work with the communication itself.