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

  • Re: SSPI delegation using kerberos
    ... We want the authentication to happen without providing credentials ... security context created in server to connect back and authenticate to ... void auth(SOCKET s, CredHandle& cred, CtxtHandle& cliCtx, ... int Ganesh_Server_Impl ...
    (microsoft.public.platformsdk.security)
  • Re: Using CWinThread in MFC apps
    ... You cannot put socket handlers in a worker thread. ... void cSocket::OnAccept(int nErrorCode) ... int cSocket::Receive ...
    (microsoft.public.vc.mfc)
  • lbreakout2server[v2-2.5+]: remote format string exploit.
    ... function to find the pop/memory location on the server. ... sending format string, new .dtors. ... char *getfmt(int,int,unsigned int); ... void getpops; ...
    (Bugtraq)
  • Re: multithreaded tcp/ip monitoring application
    ... private void btnConnect_Click ... server = new TcpClient; ... // Retrieve the state object and the handler socket ... RetryConnect function, it says invalid operationexception after executing ...
    (microsoft.public.dotnet.languages.csharp)
  • [NEWS] Zdaemon and xdoom Multiple Vulnerabilities (Buffer Overflow, DoS)
    ... So the client sends the name of each wad used on the server followed by ... static char errmsg; ... void ZD_MissingPlayer ... int which = ZD_ReadByte; ...
    (Securiteam)