2008年11月29日 星期六

HW05

// Concurrent Servers and Clients
// Under Linux
// 範例為輸入兩個double回傳總合
// 課堂上修改為輸入三個double回傳總和以及平均(須有小數點)
// 沒更動的部分用原來顏色 , 修改部分用藍色
// 注意數字型態的傳遞很重要 , 不對就一定顯示不出來

//--------------------------------------------------------------------------
// tcpcli01.c
#include "unp.h"

int main(int argc, char **argv)
{
 int sockfd;
 struct sockaddr_in servaddr;

 if (argc != 2)   
  err_quit("usage: tcpcli ");

  sockfd = Socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(SERV_PORT);
  Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

  Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

  str_cli(stdin, sockfd); /* do it all */

  exit(0);
}
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// str_cli.c
#include "unp.h"
#include "sum.h"

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

 while (Fgets(sendline, MAXLINE, fp) != NULL) {

  // Add the third argument
  if (sscanf(sendline, "%ld%ld%ld", &args.arg1, &args.arg2,&args.arg3) != 3){
   printf("invalid input: %s", sendline);
   continue;
  }
  Writen(sockfd, &args, sizeof(args));

  if (Readn(sockfd, &result, sizeof(result)) == 0)
   err_quit("str_cli: server terminated prematurely");

  printf("The sum is %ld\n", result.sum);
  // Notice the data type
  printf("The average is %lf\n", result.ave);
 }
}
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// tcpserv01.c
#include "unp.h"

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

 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(SERV_PORT);

 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

 Listen(listenfd, LISTENQ);

 Signal(SIGCHLD, sig_chld);

 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) <>
   if (errno == EINTR)
    continue; /* back to for() */
   else
    err_sys("accept error");
  }

  if ( (childpid = Fork()) == 0) { /* child process */
   Close(listenfd); /* close listening socket */
   str_echo(connfd); /* process the request */
   exit(0);
  }
  Close(connfd); /* parent closes connected socket */
 }
}
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// str_echo.c
#include "unp.h"
#include "sum.h"

void str_echo(int sockfd)
{
 ssize_t n;
 struct args args;
 struct result result;

 for ( ; ; ) {
  if ( (n = Readn(sockfd, &args, sizeof(args))) == 0)
   return; /* connection closed by other end */

  result.sum = args.arg1 + args.arg2 + args.arg3 ;
  // Count the average
  result.ave = (double)result.sum / 3 ;
  Writen(sockfd, &result, sizeof(result));
 }
}
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// sum.h
struct args {
 long arg1;
 long arg2;
 long arg3;
};

struct result {
 long sum;
 // Notice the data type
 double ave;

};
//--------------------------------------------------------------------------


//--------------------------------------------------------------------------
// Goal : 砍掉成為Zombie的子程序
// sigchldwaitpid.c
#include "unp.h"

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

 while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
  printf("child %d terminated\n", pid);
 return;
}
//--------------------------------------------------------------------------

沒有留言: