2008年11月29日 星期六

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

沒有留言: