Solved

Threaded Client Example

Posted on 2004-04-03
4
824 Views
Last Modified: 2011-10-03
2 questions:
1) Could someone write a quick threaded client socket example for me? Basically I want this to be able to run on my RH9 box and i just need a little simple template that creates a thread that creates a socket and connects to yahoo.com:80 for example.This thread that creates a socket should do the following: Send "hello" Receive some data (store it in a chr*) and then send out the data it stored once it gets a "hello"from the server...
2) I need this thread to call a metheod (void) when something special happens (i.e. Server sends "bye")

Thanks
0
Comment
Question by:e1337coderz
  • 2
4 Comments
 

Author Comment

by:e1337coderz
Comment Utility
.
0
 
LVL 4

Accepted Solution

by:
oumer earned 500 total points
Comment Utility
The point is tempting, and I have been working on threads the last few months so I can put together a full working code for you in less than 30 mintues, but it really looks like a homework to me. So instead I will give you hints on how to do the different things, and it should be more fun for you to put it together. Play with the programs, try out stuffs ...

HOW TO CREATE THREADS example
------------------------------------------------------
creating threads is simple in linux. You have to prepare a function that would be called when the thread is created, that is the thread's main function.  if you look at
man pthread_create
the format is
int  pthread_create(pthread_t  *  thread, pthread_attr_t * attr, void *
       (*start_routine)(void *), void * arg);

The first argument is the thread id, the second one the thread attributes (most of the time you don't need to use this), the third a function pointer to the thread's main function, and the last one if there is anything you want to pass into the thread. So let's create a simple program that would create two threads, they will be given some ids, they will just be doing some printing their ids , sleeping for sometime and so on till you interrupt the program (Ctrl+c ) for example.

To compile the program do gcc thread_example.c -o thread_example -lpthread
(For more information on pthreads, read at this excellent online book
http://www.mit.edu/afs/net/user/tytso/r-ready/proven.backup/book/threads.ps
)

#include <stdio.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

void * _thread (void *arg)  
//this is the entry to the thread function, always it has to be in the format void * name(void *)
{
  int *my_id = (int *) arg;
  printf ("Thread with id %d created\n",*id);
  while (true)
  {
    printf("I am thread # %d\n", *my_id);
     sleep(1);
  }
   return NULL;
}

int main (int argc, char *argv[])
{
  pthread_t   th1, th2;  //thread id has to be of type pthread_t
  int id_1=1, id_2=2;
  pthread_create (&th1, NULL, _thread, id_1);
  pthread_create(&th2, NULL, _thread, id_2);

  //Now that thread is created, the main thread has to do something, otherwise when the main
  //thread exists all the children will exit also, s  o for this simple example, we just be sleeping  //in an infinite loop
  while (true)
 {
    sleep(100);
 }
  return 0;
}

The first few lines of the output is something like

Thread with id 1 created
I am thread # 1
Thread with id 2 created
I am thread # 2
I am thread # 1
I am thread # 2
I am thread # 1
I am thread # 2
I am thread # 1
I am thread # 2


HOW TO USE SOCKETS, example



0
 
LVL 30

Expert Comment

by:Axter
Comment Utility
0
 
LVL 4

Expert Comment

by:oumer
Comment Utility
pushed submit by mistake

HOW TO USE SOCKETS, example
------------------------------------------------

For normal socket programs you need two communicating sides, one client one server. The server will be listening on some specific port for incoming connection and when it senses this connection it will spawn a connection with the client, i.e the listener will keep on listening for other connections still, but the already established connection will continue too...
(The best place to get info on sockets, UNIX network programming, by Richard Stevens)
Online stuff: This will get you started fast
http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/textcode.html)

A simple example that shows you this process ... A socket listens on say port 1234 for incoming connection, when it gets one, it will print "connection established" to the screen and it will then echo back whatever the client is writing to it ....

I have to admit I stole most of the code from stevens book. Afetr you compile the programs (Simply gcc client.c -o client and   gcc server.c -o server), you run the server as
server
in one terminal
And then you can start client programs like
client youripaddress
then type a line of text enter
You will see the text displayed both at the server and the client
you can open other clients at the same time and run all of them at the same time


Now that you have a socket program that works and a thread program that work. next step is to spawn a thread instead of a process. In the server code, I used fork for each incoming connection. Now you have to change it in such a way that a new thread is started. And in that thread's main function, you implement the protocol you want.

Give it a try and we will be glad to answer any questions .



/*Client code */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#define MAXLINE 100
#define LISTENQ 10
#define SERV_PORT 1300

static ssize_t my_read(int fd, char *ptr)
{
  static int      read_cnt = 0;
  static char      *read_ptr;
  static char      read_buf[MAXLINE];

  if (read_cnt <= 0)
    {
    again:
      if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
      if (errno == EINTR)
        goto again;
      return(-1);
      } else if (read_cnt == 0)
      return(0);
      read_ptr = read_buf;
    }
 
  read_cnt--;
  *ptr = *read_ptr++;
  return(1);
}

ssize_t readline(int fd, void *vptr, size_t maxlen)
{
  int      n, rc;
  char      c, *ptr;

  ptr = (char *) vptr;
  for (n = 1; n < maxlen; n++)
    {
      if ( (rc = my_read(fd, &c)) == 1)
      {
        *ptr++ = c;
        if (c == '\n')
          break;      /* newline is stored, like fgets() */
      } else if (rc == 0) {
        if (n == 1)
          return(0);      /* EOF, no data read */
        else
      break;            /* EOF, some data was read */
      } else
        return(-1);            /* error, errno set by read() */
    }
 
  *ptr = 0;      /* null terminate like fgets() */
  return(n);
}
/* end readline */

ssize_t Readline(int fd, void *ptr, size_t maxlen)
{
  ssize_t            n;
 
  if ( (n = readline(fd, ptr, maxlen)) < 0)
    {
      fprintf(stderr,"readline error");
      exit(-14);
    }
  return(n);
}

ssize_t       writen(int fd, const void *vptr, size_t n)
{
  size_t            nleft;
  ssize_t            nwritten;
  const char      *ptr;
 
  ptr = (const char*)vptr;
  nleft = n;
  while (nleft > 0) {
    if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
      if (errno == EINTR)
      nwritten = 0;            /* and call write() again */
      else
      return(-1);                  /* error */
    }

    nleft -= nwritten;
    ptr   += nwritten;
  }
  return(n);
}
/* end writen */

void Writen(int fd, void *ptr, size_t nbytes)
{
  if (writen(fd, ptr, nbytes) != nbytes)
    {
      fprintf(stderr,"writen error");
      exit(-14);
    }
}



/* Read "n" bytes from a descriptor. */
ssize_t      readn(int fd, void *vptr, size_t n)
{
  size_t      nleft;
  ssize_t      nread;
  char      *ptr;

  ptr = (char*) vptr;
  nleft = n;
  while (nleft > 0) {
    if ( (nread = read(fd, ptr, nleft)) < 0) {
      if (errno == EINTR)
      nread = 0;            /* and call read() again */
      else
      return(-1);
    } else if (nread == 0)
      break;                        /* EOF */

    nleft -= nread;
    ptr   += nread;
  }
  return(n - nleft);            /* return >= 0 */
}
/* end readn */

ssize_t Readn(int fd, void *ptr, size_t nbytes)
{
  ssize_t            n;

  if ( (n = readn(fd, ptr, nbytes)) < 0)
    {  
      fprintf(stderr,"readn error");
      exit(-12);
    }
  return(n);
}

void str_cli(FILE *fp, int sockfd)
{
  char      sendline[MAXLINE], recvline[MAXLINE];

  while(fgets(sendline, MAXLINE, fp) != NULL)
    {
      Writen(sockfd, sendline, strlen(sendline));
     
      //read the echo of the command execution
      if (Readline(sockfd, recvline, MAXLINE) == 0)
      {
        fprintf(stderr,"str_cli: server terminated prematurely");
        exit(-12);
      }
      fputs(recvline, stdout);
    }
}

int main(int argc, char **argv)
{

  int      sockfd;
  struct sockaddr_in      servaddr;

  if (argc != 2)
    {
      fprintf(stderr,"usage: tcpclient <IPaddress>");
      exit(-12);
    }
 
  if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
      fprintf(stderr,"socket error");
      exit(-11);
    }

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(SERV_PORT);
 
  if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
    {
      fprintf(stderr,"inet_pton error for %s", argv[1]);
      exit(-12);
    }

  if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
    {
      fprintf(stderr,"connection error");
      exit(-13);
    }
  printf("Connection Established\n");
  //shutdown(sockfd, SHUT_RDWR);
 
  str_cli(stdin, sockfd);           
}


/*server code*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <strings.h>

#define MAXLINE 100
#define LISTENQ 10
#define SERV_PORT 1300

static ssize_t my_read(int fd, char *ptr)
{
  static int      read_cnt = 0;
  static char      *read_ptr;
  static char      read_buf[MAXLINE];

  if (read_cnt <= 0)
    {
    again:
      if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
      if (errno == EINTR)
        goto again;
      return(-1);
      } else if (read_cnt == 0)
      return(0);
      read_ptr = read_buf;
    }
 
  read_cnt--;
  *ptr = *read_ptr++;
  return(1);
}

ssize_t readline(int fd, void *vptr, size_t maxlen)
{
  int      n, rc;
  char      c, *ptr;

  ptr = (char *) vptr;
  for (n = 1; n < maxlen; n++)
    {
      if ( (rc = my_read(fd, &c)) == 1)
      {
        *ptr++ = c;
        if (c == '\n')
          break;      /* newline is stored, like fgets() */
      } else if (rc == 0) {
        if (n == 1)
          return(0);      /* EOF, no data read */
        else
          break;            /* EOF, some data was read */
      } else
        return(-1);            /* error, errno set by read() */
    }
 
  *ptr = 0;      /* null terminate like fgets() */
  return(n);
}
/* end readline */

ssize_t Readline(int fd, void *ptr, size_t maxlen)
{
  ssize_t            n;
 
  if ( (n = readline(fd, ptr, maxlen)) < 0)
    {
      fprintf(stderr,"readline error");
      exit(-14);
    }
  return(n);
}

ssize_t       writen(int fd, const void *vptr, size_t n)
{
  size_t            nleft;
  ssize_t            nwritten;
  const char      *ptr;
 
  ptr = (const char*)vptr;
  nleft = n;
  while (nleft > 0) {
    if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
      if (errno == EINTR)
      nwritten = 0;            /* and call write() again */
      else
      return(-1);                  /* error */
    }

    nleft -= nwritten;
    ptr   += nwritten;
  }
  //cout << "chars written " << n << endl;
  return(n);
 
}
/* end writen */

void Writen(int fd, void *ptr, size_t nbytes)
{
  if (writen(fd, ptr, nbytes) != nbytes)
    {
      fprintf(stderr,"writen error");
      exit(-14);
    }
  //  cout << "written" << endl;
}

/* Read "n" bytes from a descriptor. */
ssize_t      readn(int fd, void *vptr, size_t n)
{
  size_t      nleft;
  ssize_t      nread;
  char      *ptr;

  ptr = (char*)vptr;
  nleft = n;
  while (nleft > 0) {
    if ( (nread = read(fd, ptr, nleft)) < 0) {
      if (errno == EINTR)
      nread = 0;            /* and call read() again */
      else
      return(-1);
    } else if (nread == 0)
      break;                        /* EOF */

    nleft -= nread;
    ptr   += nread;
  }
  return(n - nleft);            /* return >= 0 */
}
/* end readn */

ssize_t Readn(int fd, void *ptr, size_t nbytes)
{
  ssize_t            n;


  if ( (n = readn(fd, ptr, nbytes)) < 0)
    {  
      fprintf(stderr,"readn error");
      exit(-12);
    }

  return(n);
}

void echo (int sockfd, int id)
{
  ssize_t n;
  char      recvline[MAXLINE];

  printf("Connection Established with client # %d\n", id);
 
  for ( ; ; )
    {
      if ( (n=Readline(sockfd, recvline, MAXLINE)) == 0)
      {
        fprintf(stderr,"str_cli: server terminated prematurely");
        exit(-12);
      }
      //wirte it here;
      printf("From #%d\n", id);
      fputs(recvline, stdout);
     
     
      //write it back to the client
      Writen(sockfd, recvline, strlen(recvline));
    }
  //close(sockfd);
     
}



int main(int argc, char **argv)
{
  int      listenfd, connfd;
  pid_t childpid;
  int  clilen;
  int id =0;
  struct sockaddr_in      servaddr, cliaddr;

  if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
      fprintf(stderr,"socket error");
      exit(-11);
    }

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(SERV_PORT);
  servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

  if ((bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0)
    {
      fprintf(stderr,"socket bind error");
      exit(-12);
    }

  if ((listen(listenfd, LISTENQ)) < 0)
    {
      fprintf(stderr,"socket listen error");
      exit(-13);
    }

  for ( ; ; )
    {
      clilen = sizeof(cliaddr);
      if ((connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen)) < 0)
      {
        fprintf(stderr,"socket accept error");
        exit(-14);
      }
      
      if ( (childpid = fork()) == 0)
      {
        id++;
        close(listenfd);
        echo(connfd,id);
        exit(0);
      }
      close(connfd);
    }
}




0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now