0

I am trying to read the data from the file /tmp/k on the server side and copying the data to the message and sending to the client side. Here i am able to send the data to the client but my client is not able to recv() or display the data. Can anyone help me with the problem or can propose a better solution to display the data at the client side.

Thanks

client.c

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

#define MAX_SIZE 100000
#define NUM_CLIENT 5
void *connection_handler(void *);

int main(int argc , char *argv[])
{
   int sockfd;
   long i;
   pthread_t sniffer_thread;
   printf("memory allocated for the creation of socket \n");
   for (i=1; i<=NUM_CLIENT; i++) {
        if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void *) i) < 0)
    {
        perror("could not create thread");
        return 1;
    } 
    printf("Thread created \n");
    sleep(2); 
} 
pthread_exit(NULL);
return 0;
}
void *connection_handler(void *threadid)
{   
    long etid; /*each thread id */
    etid = (long)threadid;
    pthread_t tid;
    tid = pthread_self();
    int sockfd;
    struct sockaddr_in serv_addr;
    char sbuff[MAX_SIZE] , rbuff[MAX_SIZE];                             
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    printf("Failed creating socket\n");
    perror("could not create thread");
    return 0;
    }
    memset(&serv_addr, 0 , sizeof (serv_addr));
    printf("the bytes of memory area pointed by serv_addr is filled with constant '0' \n");
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(8888);

    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof (serv_addr)) < 0) {
         perror("Failed to connect to server. Error");
         return 0;
         }
    printf("Connected successfully client:%ld \n", tid);
    printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid)); 
    while(1)
    {
       printf("For thread : %ld\n", etid);
       printf("thread id given by kernel: %ld\n", tid);
       fgets(sbuff, MAX_SIZE , stdin);
       send(sockfd,sbuff,strlen(sbuff),0);

        if(recv(sockfd,rbuff,MAX_SIZE,0)==0)
           printf("Error");
       else
          fputs(rbuff,stdout);
       bzero(rbuff,MAX_SIZE);
       sleep(2);
       } 
       close(sockfd);
       return 0;
}

server.c

 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <sys/syscall.h>
 #include<pthread.h> //for threading , link with lpthread
 #include <fcntl.h>

 #define PROCESSLIST "/tmp/k"
 void *connection_handler(void *);
 int main(int argc , char *argv[])
 {
     int sockfd , new_socket , c , *new_sock;
     struct sockaddr_in server , client;
     char *message;

     //Create socket
     sockfd = socket(AF_INET , SOCK_STREAM , 0);
     if (sockfd == -1)
     {
         printf("Could not create socket");
     }

     //Prepare the sockaddr_in structure
     server.sin_family = AF_INET;
     server.sin_addr.s_addr = INADDR_ANY;
     server.sin_port = htons( 8888 );

     //Bind
     if( bind(sockfd,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
       puts("bind failed");
       return 1;
     }
     puts("bind done");

     //Listen
     listen(sockfd , 3);

    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
    while( (new_socket = accept(sockfd, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        puts("Connection accepted");

        pthread_t sniffer_thread;
        new_sock = malloc(1);
       *new_sock = new_socket;

      if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
      {
        perror("could not create thread");
        return 1;
       }
    puts("Handler assigned");
   }

   if (new_socket<0)
   {
    perror("accept failed");
    return 1;
    }

    return 0;
}

  /* This will handle connection for each client */
void *connection_handler(void *sockfd)
{
       //Get the socket descriptor
      int sock = *(int*)sockfd;
      int read_size;
      char message[100000], client_message[2000];
      int fd;
      void *buff;
      //Receive a message from client
     while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
     {
        system ("ps -ef > /tmp/k");
        puts("temp file getting created");
        fd = open (PROCESSLIST, O_RDONLY);
        puts("file open has taken place");
        read(fd, buff, sizeof(*buff));
        puts("reading the file");
        write(sock, buff, 1);
        puts("writing to the buffer");
        puts("copied data from buffer to message");
        //Send the message back to client
        send(sock,message,strlen(message),0);
        puts("data has been sent");
        }

       if(read_size == 0)
       {
       puts("Client disconnected");
       fflush(stdout);
       }
       else if(read_size == -1)
       {
          perror("recv failed");
        }

//Free the socket pointer
free(sockfd);

return 0;
}
dbush
  • 205,898
  • 23
  • 218
  • 273
nandan
  • 133
  • 1
  • 8
  • 2
    You want `popen()` instead of `system()`. – alk Sep 18 '15 at 16:04
  • Just FYI, those aren't system calls. – EOF Sep 18 '15 at 16:07
  • 1
    Or go for the *procps* (http://procps.sourceforge.net/) sources and role your own interface to the process list. – alk Sep 18 '15 at 16:08
  • I want it with only system() @alk , what happens is my client requests the server, what are the process running now and then server executes system("ps -ef > /tmp/process "), then reads characters of those file and then send them to client to display. – nandan Sep 19 '15 at 05:46
  • You want to open the file `/tmp/process` and read its content. – alk Sep 19 '15 at 08:48
  • Yes i want open and read the characters and display them in client.@alk – nandan Sep 20 '15 at 05:08

1 Answers1

0

A couple of issues:

In your server, you do this:

new_sock = malloc(1);

You're only allocating 1 byte to hold an int That's not enough space. Since newsock points to a int, you should allocate enough space for one:

new_sock = malloc(sizeof(int));

Also in the server, you're doing this after you read the message from the client:

    fd = open (PROCESSLIST, O_RDONLY);
    puts("file open has taken place");
    read(fd, buff, sizeof(*buff));
    puts("reading the file");
    write(sock, buff, 1);
    puts("writing to the buffer");
    puts("copied data from buffer to message");
    //Send the message back to client
    send(sock,message,strlen(message),0);

buff is an uninitialized void *, so attempting to write to it results in undefined behavior. The write is sending a single byte over the socket from the uninitialized buff, which is probably not what you want. Then you send data from message over the socket without putting anything into it.

All you really need to do here is read from the file directly into message, then send. You'll first want to clear the memory in message so that after you read from the file, it will be NULL terminated.

So you can replace the above with this:

    fd = open (PROCESSLIST, O_RDONLY);
    puts("file open has taken place");
    memset(message, 0, sizeof(message));
    read(fd, message, sizeof(message));
    puts("reading the file");
    //Send the message back to client
    send(sock,message,strlen(message),0);

In the client, you have 5 threads trying to read a message from the user at the same time. Only one of them will be able to. Since the server is ignoring the data send by the client, it might be better to have each client thread send some dummy data without prompting the user, then exiting once it gets the message from the server.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • @nandan Glad I could help. Feel free to [accept this answer](http://stackoverflow.com/help/accepted-answer) if you found it useful. – dbush Sep 21 '15 at 15:03
  • do you have any idea how to add message header to the server and client @dbush – nandan Sep 21 '15 at 15:26
  • @nandan You could send a fixed length field defining the message type and the length in bytes of the message. Then when you `recv` you would do it twice: once to read in the header (which is a known size), then when you get the size from the header, `recv` again expecting that many bytes. – dbush Sep 21 '15 at 15:30
  • i tried that putting message field, but now i am getting segmentation fault(core dump) error. How can i rectify it. – nandan Sep 22 '15 at 15:43
  • @nandan You're probably writing to a memory location you're not supposed to. Post a new question for this issue. – dbush Sep 22 '15 at 15:45
  • i just edited the question with the new issue.@dbush – nandan Sep 22 '15 at 15:54
  • @nandan Please don't, as that disrupts the original question that has already been solved. Please post a new question. – dbush Sep 22 '15 at 15:56
  • check this thread http://stackoverflow.com/questions/32721568/core-dump-at-client-side-after-bcopy – nandan Sep 22 '15 at 16:03