Re: sending images over a socket

From: Mike Chirico (mchirico_at_comcast.net)
Date: 12/08/03


Date: Mon, 8 Dec 2003 12:53:03 -0500


"Joaquin López" <lsanchez@lsi.uji.es> wrote in message
news:3fd4a376@news.vodafone.es...
> Hello, I'm writing a program for sending images over a socket.
>
> The size of the image is 640x480 pixels in pgm format.
>
> The problem is that when the client sends the image to the server (307200
> bytes) the server only receives 65533.

Put the read in a loop. If you do a tcpdump

  tcpdump ether src port <your port>

Look for the mss value "maximum segment size" in the 3 way hand, which
should be the number of bytes for each call to read.

/** server side **/
process_stuff(int sockfd)
{
  ssize_t n;
  char line[MAXLINE];

  sockfd_to_family(sockfd);
      while(1) {
            if ( ( n = read( sockfd, line, MAXLINE)) == 0 )
          {
            fprintf(stderr,"client had nothing else to say \n");
            return;
          }
        line[n]='\0';
        fprintf(stderr,"client said :n=%d %s\n",n,line);
      } /* end while */
}

When the client is done sending, it can exit and you can look for the
WNOHANG
/* server side */
sig_chld(int signo)
{
  pid_t pid;
  int stat;

  while( (pid = waitpid ( -1, &stat, WNOHANG)) > 0 )
    fprintf(stderr,"child %d terminated \n",pid); /* not recommended to
have a print here */
  return;

}

/******* start: Complete toy server for text******************/
#include <stdlib.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>

#define SA struct sockaddr /* keeps the lines shorter */
#define MAXLINE 4096
/* Following could be derived from SOMAXCONN in <sys/socket.h>, but many
   kernels still #define it as 5, while actually supporting many more */
#define LISTENQ 1024 /* 2nd argument to listen() */
#define MAXSOCKADDR 128 /* max socket address structure size */

/* normally these would go in a header */
void sig_chld(int);
void process_stuff(int);
int sockfd_to_family(int );

/*
  The follwing function prevents zombie or defunct processes:
  which occurs with server2way when the client is killed:

$ps -U chirico -auf
chirico 30923 0.0 0.0 1352 252 pts/0 S 11:02 0:00 \_
./server2way
chirico 30924 0.0 0.0 0 0 pts/0 Z 11:02 0:00 \_
[server2way <defunct>]

  So, the function below...prevents the problem.

*/

void
sig_chld(int signo)
{
  pid_t pid;
  int stat;

  while( (pid = waitpid ( -1, &stat, WNOHANG)) > 0 )
    fprintf(stderr,"child %d terminated \n",pid); /* not recommended to
have a print here */
  return;

}

void
process_stuff(int sockfd)
{
  ssize_t n;
  char line[MAXLINE];

  sockfd_to_family(sockfd);
  while(1) {
    if ( ( n = read( sockfd, line, MAXLINE)) == 0 )
      {
 fprintf(stderr,"return in process_stuff ... read == 0\n");
 return;

      }
    line[n]='\0';
    fprintf(stderr,"client:n=%d %s\n",n,line);
    write(sockfd, line, n);
  }
}

int
sockfd_to_family(int sockfd)
{

  struct sockaddr_in sa;
  socklen_t len;

  len = sizeof(sa);
  if (getpeername(sockfd, (struct sockaddr*) &sa, &len) < 0 )
    return -1;

  fprintf(stderr,"client: %s: %d\n",inet_ntoa(sa.sin_addr),(int)
ntohs(sa.sin_port));

  return(sa.sin_port);
}

/*

These are the major 4 steps:
  socket
  bind
  listen
    -- signal handle (optional but good if client it killed)
  accept

*/

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

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(10000); /* change this to your favorate port
*/

  bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  listen(listenfd, LISTENQ);

  signal(SIGCHLD, sig_chld);

  while(1)
    {
      clilen = sizeof(cliaddr);
      connfd = accept(listenfd, (SA *) &cliaddr, &clilen);

      if ( (childpid = fork()) == 0 ) {
 close(listenfd);
 process_stuff(connfd);
 exit(0);
      }
      close(connfd);
    }

}

/******* end: Complete toy server ******************/

Sorry about all the code; but, it's hard to understand with just pieces.

Excellent reference: "Unix Network Programming.." W. Richard Stevens.

Regards,

Mike Chirico



Relevant Pages