Hi I'm creating a socket server in Linux using pthreads. I was just wondering, how does the server send specific messages to its clients (for instance, a PM) if each is in its own standalone thread?

Well you could easily acomplish that by using some Linux C functions:
send: Click Here (also in your terminal man send)
recv: Click Here (also in your terminal man recv)

Here's a tutorial on that:
Click Here
Follow the steps Beej puts there, and you'll be fine.

Edited 3 Years Ago by Lucaci Andrew

Here's a quick example that I have cooked up. It's not bright and perhaps with many buggs (I admit, done in a jiffy :) ), but it should get you started:

What does this program do?
1. Server starts up the process by creating the connections, with a fixed (as a console argument) number of clients to connect to it, such as a fix number as its port.
2. Clients connect to the server.
3. Clients send a random number between 1 and 100, and they get back that numbered tripled.
4. Server waits for the number, triples it, and sends it back. Also, it has a counter, which will be incremented by each thread as it gets in the worker function.

Easy-peasy:

server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

//usefull structure when dealing with threads and sockets
typedef struct pd_t{
    int sock;
    pthread_t t;
}pd_t;

//some global variables
pd_t* t;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
int counter=0;

//initialization function
void init(int max){
    t=malloc (sizeof (pd_t) * max);
}

void* worker (void* arg){
    int index=(int) arg, sock=t[index].sock;

    //using threads
    printf("Thread %d increments the counter.\n", index);
    pthread_mutex_lock (&mtx);
    counter++;
    printf("The value of counter is %d.\n", counter);
    pthread_mutex_unlock (&mtx);

    //using socket communication
    int number;
    if (recv(sock, &number, sizeof(int), 0)<0) {perror ("Received"); exit(1);}
    printf("Received number: %d.\n", ntohl(number));
    number=htonl(ntohl(number)*3);  
    if (send(sock, &number, sizeof(int), 0)<0) {perror ("Sent"); exit(1);}
    printf("Sent number: %d.\n", ntohl(number)); 
    return NULL;
}

int main(int argc, char* argv[]){
    int max, i, rvsock, sock, index=0;
    unsigned short port;
    sscanf(argv[1], "%hd", &port); 
    sscanf(argv[2], "%d", &max); 

    init(max);

    rvsock=socket(AF_INET, SOCK_STREAM, 0);
    if (rvsock<0){perror("RVSock: ");exit(1);}

    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    memset(&server_addr, 0, sizeof(server_addr)); //fill up the space with 0's
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);


    //the error checking is crucial
    if (bind (rvsock, (struct sockaddr*) &server_addr, sizeof(server_addr))<0) {
        perror("Bind"); //tries to open a rande-vous socket for connection
        exit(1);
    }

    if (listen(rvsock, max)<0) {
        perror ("Listen"); //listens for 'max' clients
        exit(1);
    }   

    printf("Now I'm waiting for clients to connect.\n");
    unsigned int length;
    while(1){
        if (index==max) break;
        sock=accept(rvsock, (struct sockaddr*) &client_addr, &length);
        if (sock<0) {perror ("Client accept: "); break;}
        t[index].sock=sock;     
        pthread_create(&t[index].t, NULL, worker, (void*)index);            
        index++;
    }

    //joins the threads
    for (i=0;i<max;i++){
        pthread_join (t[i].t, NULL);    
    }

    printf("The counter now has the value of %d.\n", counter);

    free (t);

    return 0;
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

int main(int args, char* argv []){
    unsigned short port;
    sscanf(argv[1], "%hd", &port);
    srand (time (0));

    int number=rand()%100+1, ret, sock;
    sock=socket(AF_INET, SOCK_STREAM, 0);

    if (sock<0){
        perror("Sock: ");
        exit(1);
    }

    struct sockaddr_in saddr;
    memset (&saddr, 0, sizeof(saddr));
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr= inet_addr("127.0.0.1"); //local ip
    saddr.sin_port=htons(port); 

    //connects to the server
    ret=connect (sock, (struct sockaddr*) &saddr, sizeof(saddr));
    if (ret<0){
        perror("Connect: ");
        exit(1);
    }

    number=htonl(number); //converts to network standard endian notation;
    if (send(sock, &number, sizeof(int), 0)<0){
        perror("Sent");
        exit(1);
    }

    printf("Sent number %d.\n", ntohl(number));

    if (recv(sock, &number, sizeof(int), 0)<0){
        perror("Receive: ");
        exit(1);
    }

    printf("Received number %d.\n", ntohl(number));

    close (sock);

    return 0;
}

Compiling:

$ gcc -Wall -o server server.c -lpthread
$ gcc -Wall -o client client.c

Runnin + output:
1. Server's terminal:

$ ./server 12345 2
Now I'm waiting for clients to connect.
Thread 0 increments the counter.
The value of counter is 1.
Received number: 65.
Sent number: 195.
Thread 1 increments the counter.
The value of counter is 2.
Received number: 14.
Sent number: 42.
The counter now has the value of 2.
  1. Client's terminal:

    $ ./client 12345
    Sent number 65.
    Received number 195.
    $ ./client 12345
    Sent number 14.
    Received number 42.

Run server than client.

Edited 3 Years Ago by Lucaci Andrew

This article has been dead for over six months. Start a new discussion instead.