Link to home
Start Free TrialLog in
Avatar of e1337coderz
e1337coderz

asked on

Threaded Client Example

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
Avatar of e1337coderz
e1337coderz

ASKER

.
ASKER CERTIFIED SOLUTION
Avatar of oumer
oumer

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Axter
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);
    }
}