2008年11月30日 星期日

Knight's Tour using recursive programing


/* 若是用遞迴,對於棋盤格數較多則時間會花很久 ( 注意並非無限迴圈 ) */


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define col_size 5
#define row_size 5

void clear();
int knight(int,int);

int checker[row_size+4][col_size+4];
int step=0;
int ans=0;
// Knight's directions in X-axis and Y-axis.
const int horizontal[8]={ 2, 1,-1,-2,-2,-1, 1, 2};
const int vertical[8]={-1,-2,-2,-1, 1, 2, 2, 1}; 

int main()
{
time_t ticks1,ticks2;
int i,j,p,t;
clear();

ticks1 = time(NULL);

for(p=2;p<row_size+2;p++)
for(t=2;t<col_size+2;t++)
if(knight(p,t)==row_size*col_size)
{
printf("\nAns : %d\tStep : %d\n",++ans,step);
for(i=2;i<row_size+2;i++)
{
for(j=2;j<col_size+2;j++)
printf("%3d",checker[i][j]);
printf("\n");
}
clear();
}

ticks2 = time(NULL);

printf("\nStart time : %.24s\r\n",ctime(&ticks1));
printf(" End time : %.24s\r\n",ctime(&ticks2));

system("PAUSE");
return 0;
}

// To avoid that the knight goes out of range.
void clear()
{
int i,j;
for(i=0;i<row_size+4;i++)
for(j=0;j<col_size+4;j++)
if(i<2||i>row_size+1||j<2||j>col_size+1)
checker[i][j]=-1;
else
checker[i][j]=0;
step=0;
}

// Find the path.
int knight(int i,int j)
{
 // Set the step right now.
checker[i][j]=++step;

int p;

 // If the checker board is not full then find the next step.
if(step<row_size*col_size)
for(p=0;p<8;p++)
// Test the eight directions.
if(checker[i+vertical[p]][j+horizontal[p]]==0)
knight(i+vertical[p],j+horizontal[p]);

 // If the checker board is full then return,
 // otherwise clear the last step and restart from last step.
if(step==col_size*row_size)
return step;
--step;
checker[i][j]=0;

return step;
}

2008年11月29日 星期六

Minimum and Maximum

// Find the maximum and minimum. Using non-recursive programming.
// Input file:void
// Output:Stdout (show on monitor)

int Minimum(char A[],int size)
{
 int min=A[0];
 int i;
 for(i=1;i>A[i];i++)
  min=A[i];
 return min;
}

int Maximum(char A[],int size)
{
 int max=A[0];
 int i;
 for(i=1;i>A[i];i++)
  max=A[i];
 return max;
}

Randomized-Select to find the ith smallest element

// Find the ith smallest element of the array A[p..r]. Using non-recursive programming.
// Input file:void
// Output:Stdout (show on monitor)

int Randomized_Select(char A[],int p,int r,int i)
{
 if(p==r)
  return A[p];
 int q=Randomized_Partition(A,p,r);
 int k=q-p+1;
 if(i==k) // the pivot is the answer
  return A[q];
 else if(ii-k);
}

// Using randomized method to find the KEY
int Randomized_Partition(char A[],int p,int r)
{
 int i=rand()%(r-p+1)+p;
 Swap(A,r,i);
 return Partition(A,p,r);
}

// Comparision and divide (1.> KEY 2.<= KEY)
int Partition(char A[],int p,int r)
{
 int x=A[r];
 int i=p-1;
 int j;
 for(j=p;j<=r-1;j++)
  if(A[j]<=x)
   Swap(A,++i,j);
 Swap(A,i+1,r);
 return i+1;
}

// Exchange two elements of the data
void Swap(char A[],int i,int j)
{
 int temp=A[i];
 A[i]=A[j];
 A[j]=temp;
 return;
}

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

新網誌

無名最近有點糟糕
太容易連結到了吧
一堆廣告商來留言回話
不喜歡 ...太商業化的東西
不適合用來當部落格
希望這個空間能夠乾淨清爽點

不過介面比較難以使用
好像有很多語法跟樣本要會設定才可以
慢慢研究囉 XD
文章都是一次顯示全部
若是只想顯示標題請參考 : 如何讓Blogger只顯示標題

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