顯示具有 UNIX Network Programing 標籤的文章。 顯示所有文章
顯示具有 UNIX Network Programing 標籤的文章。 顯示所有文章

2008年11月29日 星期六

Midterm ex6

Please add a signal handler to the above server so that there won't be any zombie process.

/* 修改 ex5 部分用藍色表示 */

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

struct ans
{
 int answer;
};

void guess(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];
 struct ans ans;

 printf("Please guess a number between 1 and 100:\n");
 do {
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   if (sscanf(sendline, "%d", &ans.answer)!=1)
    printf("Invalid input: %s", sendline);
   else if (ans.answer>100 || ans.answer<1) sockfd =" Socket(AF_INET," sin_family =" AF_INET;" sin_port =" htons(SERV_PORT);" style="color: rgb(0, 153, 0);">/* do it all */
 exit(0);
}
//-------------------------------------------------------------------------------------------


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

struct ans
{
 int answer;
};

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

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

void retrt(int sockfd)
{
 char buf[MAXLINE];
 ssize_t n;
 struct ans ans;
 int result;

 srand(time(NULL));
 result=rand()%100+1;
 printf("The answer is %d\n",result);
 do {
  if ( (n = Readn(sockfd, &ans, sizeof(ans))) == 0)
   return; /* connection closed by other end */
  if (ans.answer>result) strcpy(buf,"Guess a smaller number!\n");
  else if (ans.answer
  else strcpy(buf,"You got the answer!\n");
  Writen(sockfd, buf, strlen(buf));
 } while (strcmp(buf,"You got the answer!\n")!=0);
}

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

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

 Listen(listenfd, LISTENQ);

 Signal(SIGCHLD, sig_chld);
 
 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

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

Midterm ex5

Please revise the above program so that many clients can play the number-guessing game with the concurrent server.

/* 修改 ex4 部分用藍色表示 */

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

struct ans
{
 int answer;
};

void guess(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];
 struct ans ans;

 printf("Please guess a number between 1 and 100:\n");
 do {
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   if (sscanf(sendline, "%d", &ans.answer)!=1)
    printf("Invalid input: %s", sendline);
   else if (ans.answer>100 || ans.answer<1)>");

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

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

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


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

struct ans
{
 int answer;
};

void retrt(int sockfd)
{
 char buf[MAXLINE];
 ssize_t n;
 struct ans ans;
 int result;

 srand(time(NULL));
 result=rand()%100+1;
 printf("The answer is %d\n",result);
 do {
  if ( (n = Readn(sockfd, &ans, sizeof(ans))) == 0)
   return; /* connection closed by other end */
  if (ans.answer>result) strcpy(buf,"Guess a smaller number!\n");
  else if (ans.answer
  else strcpy(buf,"You got the answer!\n");
  Writen(sockfd, buf, strlen(buf));
 } while (strcmp(buf,"You got the answer!\n")!=0);
}

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

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

 Listen(listenfd, LISTENQ);

 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

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

Midterm ex4

Please design a number-guessing game, such that the client sends an integer to the server. After received the integer, the server compares the integer with its answer and sends a reply to the client. If the integer is greater than the answer, the server sends the string "Guess a smaller number!" to the client; if the integer is smaller than the answer, the server send the string "Guess a greater number!" to the client. Otherwise, the server sends the string "You got the answer!" to the client and the connection is closed. Note that, the answer is between 1 and 100, and it is randomly generated, the guessing-number is inputted from the keyboard.

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

struct ans
{
 int answer;
};

void guess(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];
 struct ans ans;

 printf("Please guess a number between 1 and 100:\n");
 do {
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   if (sscanf(sendline, "%d", &ans.answer)!=1)
    printf("Invalid input: %s", sendline);
   else if (ans.answer>100 || ans.answer<1)>");

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

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

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


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

struct ans
{
 int answer;
};

void retrt(int sockfd)
{
 char buf[MAXLINE];
 ssize_t n;
 struct ans ans;
 int result;

 srand(time(NULL));
 result=rand()%100+1;
 printf("The answer is %d\n",result);
 do {
  if ( (n = Readn(sockfd, &ans, sizeof(ans))) == 0)
   return; /* connection closed by other end */
  if (ans.answer>result) strcpy(buf,"Guess a smaller number!\n");
  else if (ans.answer
  else strcpy(buf,"You got the answer!\n");
  Writen(sockfd, buf, strlen(buf));
 } while (strcmp(buf,"You got the answer!\n")!=0);
}

int main(int argc, char **argv)
{
 int listenfd, connfd;

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

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

 Listen(listenfd, LISTENQ);

 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

  retrt(connfd); /* process the request */
  
  Close(connfd); /* parent closes connected socket */
 }
}
//-------------------------------------------------------------------------------------------

Midterm ex3

Please revise the above program so that the server will convert the IP address of the client and the server to numbers. Note that, the numbers should be shown on the console of the server. (Remember to check the correctness of the numbers.)

/* 修改 ex2 的部分用藍色顯示,位指轉數字要用ntohl() 轉才不會有 byte order 的問題 ( 即 a*128^3+b*128^2+c*128^1+d*128^0 變成 a*128^0+b*128^2+c*128^2+d*128^3 )*/

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

void inexp(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];

 do {
  printf("Please enter an expression (e.g. 123+456):\n");
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   Writen(sockfd, sendline, strlen(sendline));
   if (Readline(sockfd, recvline, MAXLINE) == 0)
    err_quit("inexp: server terminated prematurely");
   Fputs(recvline, stdout);
  }
 } while (strlen(recvline)>10);
}

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

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

 sockfd = Socket(AF_INET, SOCK_STREAM, 0);

 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 if (sscanf(argv[2],"%d", &port)==1)
  servaddr.sin_port = htons(port);
 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

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

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

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


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

void retrt(int sockfd)
{
 char buf[MAXLINE], rep[MAXLINE], op;
 int a, b;
 int success=0;

 do
 {
  a=b=0;
  if (read(sockfd, buf, MAXLINE)>0)
  {
   printf("Received expression: %s\n",buf);
   if (sscanf(buf, "%d%c%d",&a, &op, &b)!=3)
    snprintf(rep, sizeof(rep), "Invalid input: %s\n", buf);
   else if (a>=100 && a<=999 && b>=100 && b<=999)
   {
     switch(op)
    {
     case '+': snprintf(rep, sizeof(rep), "%d\n", a+b); success=1;
     break;
     case '-': snprintf(rep, sizeof(rep), "%d\n", a-b); success=1;
     break;
     case '*': snprintf(rep, sizeof(rep), "%d\n", a*b); success=1;
     break;
     case '/': snprintf(rep, sizeof(rep), "%d\n", a/b); success=1;
     break;
     case '%': snprintf(rep, sizeof(rep), "%d\n", a%b); success=1;
     break;
     default: snprintf(rep, sizeof(rep), "Invalid operator: %c\n", op);
    }
   }
   else
    snprintf(rep, sizeof(rep), "Invalid number: %d or %d\n", a, b);
   Writen(sockfd, rep, strlen(rep));
  }
 } while(success==0);
}

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

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

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

 bzero(&localaddr, sizeof(localaddr));
 addrlen = sizeof(localaddr);

bzero(&localaddr, sizeof(localaddr));
addrlen = sizeof(localaddr);

 if (getsockname(listenfd, (SA *) &localaddr, &addrlen)==0)
 {
  printf("Server's IP address: %s\n", inet_ntoa(localaddr.sin_addr));
  printf("Server's port number: %d\n\n", ntohs(localaddr.sin_port));
 }

 Listen(listenfd, LISTENQ);
 
 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  connfd = Accept(listenfd, (SA *) NULL, NULL);
  bzero(&localaddr, sizeof(localaddr));
  addrlen = sizeof(localaddr);
  if (getsockname(connfd, (SA *) &localaddr, &addrlen)==0)
  {
   printf("Server's IP address: %s\n", inet_ntoa(localaddr.sin_addr));
   printf("Server's port number: %d\n\n", ntohs(localaddr.sin_port));
   printf("Server's IP number: %d\n\n", ntohl(localaddr.sin_addr.s_addr));
  }

  bzero(&peeraddr, sizeof(peeraddr));
  addrlen = sizeof(peeraddr);
  if (getpeername(connfd, (SA *) &peeraddr, &addrlen)==0)
  {
   printf("Client's IP address: %s\n", inet_ntoa(peeraddr.sin_addr));
   printf("Client's port number: %d\n\n", ntohs(peeraddr.sin_port));
   printf("Server's IP number: %d\n\n", ntohl(localaddr.sin_addr.s_addr));
  }

  if ( (childpid = Fork()) == 0) { /* child process */
   Close(listenfd); /* close listening socket */
   retrt(connfd); /* process the request */
   exit(0);
  }

  Close(connfd);
 }
}
//-------------------------------------------------------------------------------------------

Midterm ex2

Please revise the above simple calculator so that the server won't bind a specific IP address and port to its sockets and it will show the IP address and port number of both the client and the server after the connection between the client and the server has been established.

/* Port 要用 ntohs() 去轉,否則會有 byte order 的問題,
getsockname() 及 getpeername() 前要先 bezero() 結果才不會不正常。 */

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

void inexp(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];

 do {
  printf("Please enter an expression (e.g. 123+456):\n");
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   Writen(sockfd, sendline, strlen(sendline));
   if (Readline(sockfd, recvline, MAXLINE) == 0)
    err_quit("inexp: server terminated prematurely");
   Fputs(recvline, stdout);
  }
 } while (strlen(recvline)>10);
}

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

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

 sockfd = Socket(AF_INET, SOCK_STREAM, 0);

 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 if (sscanf(argv[2],"%d", &port)==1)
  servaddr.sin_port = htons(port);
 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

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

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

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


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

void retrt(int sockfd)
{
 char buf[MAXLINE], rep[MAXLINE], op;
 int a, b;
 int success=0;

 do
 {
  a=b=0;
  if (read(sockfd, buf, MAXLINE)>0)
  {
   printf("Received expression: %s\n",buf);
   if (sscanf(buf, "%d%c%d",&a, &op, &b)!=3)
    snprintf(rep, sizeof(rep), "Invalid input: %s\n", buf);
   else if (a>=100 && a<=999 && b>=100 && b<=999)
   {
     switch(op)
    {
     case '+': snprintf(rep, sizeof(rep), "%d\n", a+b); success=1;
     break;
     case '-': snprintf(rep, sizeof(rep), "%d\n", a-b); success=1;
     break;
     case '*': snprintf(rep, sizeof(rep), "%d\n", a*b); success=1;
     break;
     case '/': snprintf(rep, sizeof(rep), "%d\n", a/b); success=1;
     break;
     case '%': snprintf(rep, sizeof(rep), "%d\n", a%b); success=1;
     break;
     default: snprintf(rep, sizeof(rep), "Invalid operator: %c\n", op);
    }
   }
   else
    snprintf(rep, sizeof(rep), "Invalid number: %d or %d\n", a, b);
   Writen(sockfd, rep, strlen(rep));
  }
 } while(success==0);
}

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

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

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

 bzero(&localaddr, sizeof(localaddr));
 addrlen = sizeof(localaddr);

 if (getsockname(listenfd, (SA *) &localaddr, &addrlen)==0)
 {
  printf("Server's IP address: %s\n", inet_ntoa(localaddr.sin_addr));
  printf("Server's port number: %d\n\n", ntohs(localaddr.sin_port));
 }

 Listen(listenfd, LISTENQ);
 
 for ( ; ; ) {
  clilen = sizeof(cliaddr);
  connfd = Accept(listenfd, (SA *) NULL, NULL);

  bzero(&localaddr, sizeof(localaddr));
  addrlen = sizeof(localaddr);

  if (getsockname(connfd, (SA *) &localaddr, &addrlen)==0)
  {
   printf("Server's IP address: %s\n", inet_ntoa(localaddr.sin_addr));
   printf("Server's port number: %d\n\n", ntohs(localaddr.sin_port));
  }

  bzero(&peeraddr, sizeof(peeraddr));
  addrlen = sizeof(peeraddr);

  if (getpeername(connfd, (SA *) &peeraddr, &addrlen)==0)
  {
   printf("Client's IP address: %s\n", inet_ntoa(peeraddr.sin_addr));
   printf("Client's port number: %d\n\n", ntohs(peeraddr.sin_port));
  }

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

Midterm ex1

Please a design a simple calculator client and server such that the client sends an expression (e.g."123+456), which contains two operands and an operator, to the server. After received the expression, the server replies the caculating result to the client. Note that, the operands are 3-digit integer, the operator is in {+,-,*,/,%}, the expression is inputted from the keyboard, and the caculating result should be shown on the console of the client.

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

void inexp(FILE *fp, int sockfd)
{
 char sendline[MAXLINE], recvline[MAXLINE];

 do {
  printf("Please enter an expression (e.g. 123+456):\n");
  if (Fgets(sendline, MAXLINE, fp) != NULL) {
   Writen(sockfd, sendline, strlen(sendline));
   if (Readline(sockfd, recvline, MAXLINE) == 0)
    err_quit("inexp: server terminated prematurely");
   Fputs(recvline, stdout);
  }
 } while (strlen(recvline)>10);
}

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

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

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


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

void retrt(int sockfd)
{
 char buf[MAXLINE], rep[MAXLINE], op;
 int a, b;
 int success=0;

 do
 {
  a=b=0;
  if (read(sockfd, buf, MAXLINE)>0)
  {
   printf("Received expression: %s\n",buf);
   if (sscanf(buf, "%d%c%d",&a, &op, &b)!=3)
    snprintf(rep, sizeof(rep), "Invalid input: %s\n", buf);
   else if (a>=100 && a<=999 && b>=100 && b<=999)
   {
    switch(op)
    {
     case '+': snprintf(rep, sizeof(rep), "%d\n", a+b); success=1;
     break;
     case '-': snprintf(rep, sizeof(rep), "%d\n", a-b); success=1;
     break;
     case '*': snprintf(rep, sizeof(rep), "%d\n", a*b); success=1;
     break;
     case '/': snprintf(rep, sizeof(rep), "%d\n", a/b); success=1;
     break;
     case '%': snprintf(rep, sizeof(rep), "%d\n", a%b); success=1;
     break;
     default: snprintf(rep, sizeof(rep), "Invalid operator: %c\n", op);
    }
   }
   else snprintf(rep, sizeof(rep), "Invalid number: %d or %d\n", a, b);
   Writen(sockfd, rep, strlen(rep));
  }
 } while(success==0);
}

int main(int argc, char **argv)
{
 int listenfd, connfd;
 struct sockaddr_in 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(SERV_PORT);

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

 Listen(listenfd, LISTENQ);

 for ( ; ; ) {
  connfd = Accept(listenfd, (SA *) NULL, NULL);
  retrt(connfd); /* process the request */
  Close(connfd);
 }
}
//---------------------------------------------------------------------------------------------

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;
}
//--------------------------------------------------------------------------

HW08

/* Goal : Please design a simple calculator client and server, such that client sends an expression (e.g."123+456"), which contains two operands and an operator, to the server. After received the expression, the server replies the calculating result to the client. Note that, the operands are 3-digit integer, the operator is in {+,-,*,/,%}, the expression is inputted from the keyboard, and the calculating result should be shown on the console of the client. */
//---------------------------------------------------------------------------------------------
//Input : Stdin
//Output : Stdout
//Note : 使用 UDP 協定 , 修改部分用藍色表示
//---------------------------------------------------------------------------------------------
// dg_cli is in udpcli01.c
// dg_echo is in udpserv01.c

#include "unp.h"

void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
 int n;
 char sendline[MAXLINE], recvline[MAXLINE + 1];

 socklen_t len;
 struct sockaddr *preply_addr;

 preply_addr=malloc(servlen);

 while (Fgets(sendline, MAXLINE, fp) != NULL)
 {
  Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

  len=servlen;

  n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

  printf("reply from %s (ignore)\n",Sock_ntop(preply_addr,len));

  recvline[n] = 0; /* null terminate */
  Fputs(recvline, stdout);
 }
}

void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)
{
 long arg1,arg3;
 char arg2;

 int n;
 socklen_t len;
 char mesg[MAXLINE];

 for ( ; ; )
 {  
  len = clilen;
  n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

  if(sscanf(mesg,"%ld%c%ld",&arg1,&arg2,&arg3)==3)
   if(arg1<100||arg1>999||arg3<100||arg3>999)
    snprintf(mesg,sizeof(mesg),"%s\n","invalid operand");
   else
    switch(arg2)
    {
     case '+':
      snprintf(mesg,sizeof(mesg),"%ld\n",arg1+arg3);
      break;
     case '*':
      snprintf(mesg,sizeof(mesg),"%ld\n",arg1*arg3);
      break;
     case '-':    
      snprintf(mesg,sizeof(mesg),"%ld\n",arg1-arg3);
      break;
     case '/':
      snprintf(mesg,sizeof(mesg),"%ld\n",arg1/arg3);
      break;
     case '%':
      snprintf(mesg,sizeof(mesg),"%ld\n",arg1%arg3);
      break;
     default:
      snprintf(mesg,sizeof(mesg),"%s\n","invalid operantor");
      break;
    }

  Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
 }
}