[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Threaded Client Example

Posted on 2004-04-03
4
Medium Priority
?
855 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 

Author Comment

by:e1337coderz
ID: 10750375
.
0
 
LVL 4

Accepted Solution

by:
oumer earned 2000 total points
ID: 10751239
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
ID: 10751265
0
 
LVL 4

Expert Comment

by:oumer
ID: 10751371
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

650 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