網絡編程—TCP

/*******************************************************/

網絡基礎編程

/*******************************************************/

//common.h頭文件

#ifndef __COMMON_H__
#define __COMMON_H__   //定義頭文件common.h

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <error.h>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>   //包含的頭文件

#define Err_sys(info) /      //定義錯誤處理函數
 { fprintf(stderr, "%s %s/n", info, strerror(errno));  /
  exit(EXIT_FAILURE);     /
 }

#define addrsize sizeof(struct sockaddr_in)     //套接字信息sockaddr_in結構體的大小

#define port 8888    //端口號
#define backlog 10
#define BUFFERSIZE 1024   //緩衝區大小

#define RUNNING 1   //運行狀態

#endif


/***********************************************************************/

服務器端:

#include "common.h"

int main (int argc, char *argv[])
{
 int sockfd = -1, newfd  = -1;
 struct sockaddr_in server_addr, client_addr;   //保存套接字結構信息服務器和客服端信息
 socklen_t addrlen = addrsize;

 char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
 int rc, wc;

 sockfd = socket(PF_INET, SOCK_STREAM, 0);  //建立socket連接
 if(sockfd == -1)
  Err_sys("Server socket")
 
 bzero(&server_addr,  addrsize);
 server_addr.sin_family = PF_INET;
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
 server_addr.sin_port = htons(port);
 
 int i = 1;  //允許重複使用本地地址與套接字進行綁定
 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use

 if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)  //綁定函數bind()
 {
  close(sockfd);
  Err_sys("Server bind")
 }


 if(listen(sockfd, 10) == -1)  //調用listen()函數,監聽,隊列中允許的最大請求數
 {
  close(sockfd);
  Err_sys("Server listen")
 }
   
 bzero(&client_addr, addrsize);
 
 printf("Waiting a new connection/n");
ee: newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);  //調用accept()函數,等待客服端的連接
 if(newfd == -1)
 {
   if(errno == EINTR)
     goto ee;
 }
 else
  printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

 
 memset(buffer_r, '/0', BUFFERSIZE);
 
 while(RUNNING)
 {
   memset(buffer_r, '/0', BUFFERSIZE);
   rc = recv(newfd, buffer_r, BUFFERSIZE, 0);  //接收客服端發來的信息
   if(rc <= 0)
   {
     if(rc == 0)
     {
      printf("Client has been closed/n");
     }
     close(newfd);
     close(sockfd);
     exit(EXIT_FAILURE);
   } 
   else
     printf("[Server recv]:%s/n", buffer_r);
   
   
   memset(buffer_w, '/0', BUFFERSIZE);
   printf("[Server send]:");
   fflush(stdout);
   
   fgets(buffer_w, BUFFERSIZE, stdin);  
   wc = send(newfd, buffer_w, strlen(buffer_w), 0);  //發送信息到客服端
   if(wc < 0)
   {
     close(sockfd);
     close(newfd);
     
     Err_sys("Server send")
   }
 }//while  
  close(sockfd);
  close(newfd);

  exit(EXIT_SUCCESS);
}
/****************************************************************/

 客戶端:

#include "common.h"

int main(int argc, char **argv)
{
  int sockfd = -1;
  struct sockaddr_in server_addr;   //定義套接字結構體保持socket信息
  
  char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];    //定義讀緩衝和寫緩衝
  socklen_t addrlen = addrsize;    //設置結構體大小
  
  int wc, rc;
  
  if(argc != 5)
  {
    fprintf(stderr, "%s -p port -i ip/n", argv[0]);
    exit(EXIT_FAILURE);
  }
  
  
  sockfd = socket(PF_INET, SOCK_STREAM, 0);   //建立socket連接
  if(sockfd == -1)
   Err_sys("Client socket")
   
  bzero(&server_addr, addrsize);    //設置sockaddr_in結構體中相關參數
  server_addr.sin_family = PF_INET;
  server_addr.sin_addr.s_addr = inet_addr(argv[4]);
  server_addr.sin_port = htons(atoi(argv[2]));

  int count = 0; //調用connect()函數主動發起對服務器端的連接
  while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
  {
    if(count++ <= 3)   //連接成功
    {
      fprintf(stderr, "Client is trying to connect.../n");
      sleep(3);
    }
    else    //連接失敗
    {
      fprintf(stderr, "Client connects failurefully/n");
      close(sockfd); //shutdown(sockfd, SHUT_RDWR);
      exit(EXIT_FAILURE);
    }
     
  }
  
  while(RUNNING)  //運行時
  {
    memset(buffer_w, '/0', BUFFERSIZE);
    
    printf("[Client send]:");
    fflush(stdout);
    fgets(buffer_w, BUFFERSIZE, stdin);   //獲取標準輸入的內容 存到緩衝區
    
    wc = send(sockfd, buffer_w, strlen(buffer_w), 0);    //發送消息給服務器端
    if(wc < 0)
      Err_sys("Client send")
    
  //printf("111111111111111111111/n");
    memset(buffer_r, '/0', BUFFERSIZE);
    rc = recv(sockfd, buffer_r, BUFFERSIZE, 0);   //收到服務器發來的消息 
    if(rc <= 0)
    {
      if(rc == 0)
      {
       printf("Server has been closed/n");
      }
      close(sockfd);
      exit(EXIT_FAILURE);
    } 
    else
      printf("[Client recv]:%s/n", buffer_r);
      
  }//while
  
  close(sockfd);
  
  exit(EXIT_SUCCESS); 
}      
       
/***********************************************************************/

服務器端2:

 #include "common.h"

int main (int argc, char *argv[])
{
 
 int sockfd = -1, newfd  = -1;
 struct sockaddr_in server_addr, client_addr;
 socklen_t addrlen = addrsize;

 char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
 int rc, wc;

 
 int i = 1;
 
 sockfd = socket(PF_INET, SOCK_STREAM, 0);
 if(sockfd == -1)
  Err_sys("Server socket")
 
 bzero(&server_addr,  addrsize);
 server_addr.sin_family = PF_INET;
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
 server_addr.sin_port = htons(port);

 if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
 {
  close(sockfd);
  Err_sys("Server bind")
 }


 if(listen(sockfd, 10) == -1)
 {
  close(sockfd);
  Err_sys("Server listen")
 }
   
 bzero(&client_addr, addrsize);
 
 printf("Waiting a new connection/n");
ee: newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
 if(newfd == -1)
 {
   if(errno == EINTR)
     goto ee;
 }
 else
  printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

 
 memset(buffer_r, '/0', BUFFERSIZE);
 rc = recv(newfd, buffer_r, BUFFERSIZE, 0);
 if(rc <= 0)
 {
   if(rc == 0)
   {
    printf("Client has been closed/n");
   }
   close(newfd);
   close(sockfd);
   exit(EXIT_FAILURE);
 } 
 else
   printf("[Server recv]:%s/n", buffer_r);
   
  close(sockfd);
  close(newfd);

  exit(EXIT_SUCCESS);
}
/************************************************************************/

客戶端2:

 #include "common.h"

int main(int argc, char **argv)
{
  int sockfd = -1;
  struct sockaddr_in server_addr;
  
  char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
  socklen_t addrlen = addrsize;
  
  int wc, rc;
  
  if(argc != 5)
  {
    fprintf(stderr, "%s -p port -i ip/n", argv[0]);
    exit(EXIT_FAILURE);
  }
  
  
  sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if(sockfd == -1)
   Err_sys("Client socket")
   
  bzero(&server_addr, addrsize);
  server_addr.sin_family = PF_INET;
  server_addr.sin_addr.s_addr = inet_addr(argv[4]);
  server_addr.sin_port = htons(atoi(argv[2]));

  int count = 0; 
  while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
  {
    if(count++ <= 3)
    {
      fprintf(stderr, "Client is trying to connect.../n");
      sleep(3);
    }
    else
    {
      fprintf(stderr, "Client connects failurefully/n");
      close(sockfd); //shutdown(sockfd, SHUT_RDWR);
      exit(EXIT_FAILURE);
    }
     
  }
  
  memset(buffer_w, '/0', BUFFERSIZE);
  
  printf("Please input the sending message:");
  fflush(stdout);
  fgets(buffer_w, BUFFERSIZE, stdin);
  
  wc = send(sockfd, buffer_w, strlen(buffer_w), 0);
  if(wc < 0)
    Err_sys("Client send")
  
  exit(EXIT_SUCCESS);
}

/**************************************************************/

TCP多進程併發通信

/***************************************************************/    

服務器端:

 #include "common.h"

void sig_chld(int signo)
{
  psignal(signo, "Catch signal");
  
  int status;
  while(wait(&status) == -1);
  signal(SIGCHLD, sig_chld);
}


int main (int argc, char *argv[])
{
 
 int sockfd = -1, newfd  = -1;
 struct sockaddr_in server_addr, client_addr;
 socklen_t addrlen = addrsize;

 char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
 int rc, wc;
 
 pid_t pt;
 
 fd_set readfds;
 int maxfd;
 struct timeval tv;
 int ret = -1;

 signal(SIGCHLD, sig_chld);

 sockfd = socket(PF_INET, SOCK_STREAM, 0);
 if(sockfd == -1)
  Err_sys("Server socket")
 
 bzero(&server_addr,  addrsize);
 server_addr.sin_family = PF_INET;
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
 server_addr.sin_port = htons(port);
 
 int i = 1;
 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use

 if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
 {
  close(sockfd);
  Err_sys("Server bind")
 }


 if(listen(sockfd, 10) == -1)
 {
  close(sockfd);
  Err_sys("Server listen")
 }
   
 while(RUNNING)
 {
    printf("Waiting a new connection/n");
    
    newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
    if(newfd == -1)
    {
      if(errno == EINTR)
        continue;
        
      Err_sys("Server accept")
    }
    else
      printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
   
    pt = fork();   //創建子進程
    if(pt == -1)
    {
      close(newfd);
      close(sockfd);
      Err_sys("Fork")
    }
    else if(pt == 0) //child process
    {
      close(sockfd);
      
      while(RUNNING)
      {
        maxfd = newfd;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        
        FD_ZERO(&readfds);
        FD_SET(0, &readfds);//FD_SET(STDIN_FILENO, &readfds);
        FD_SET(newfd, &readfds);
       
        ret = select(maxfd + 1, &readfds, NULL, NULL, &tv);
        switch(ret)
        {
          case -1:
            if(errno == EINTR)
              continue;
            Err_sys("Server select")
          case 0:
            //printf("Server timeout/n");
            continue;
          default:
            if(FD_ISSET(newfd, &readfds))
            {
              memset(buffer_r, '/0', BUFFERSIZE);
              rc = recv(newfd, buffer_r, BUFFERSIZE, 0);
              if(rc <= 0)
              {
                if(rc == 0)
                {
                 FD_CLR(sockfd, &readfds);  
                 printf("Client has been closed/n");
                }
                close(newfd);
                close(sockfd);
                exit(EXIT_FAILURE);
              } 
              else
                printf("[Server recv]:%s/n", buffer_r);
            }//recv
            
            if(FD_ISSET(0, &readfds))
            {
              memset(buffer_w, '/0', BUFFERSIZE);
              printf("[Server send]:");
              fflush(stdout);
              
              fgets(buffer_w, BUFFERSIZE, stdin);  
              wc = send(newfd, buffer_w, strlen(buffer_w), 0);
              if(wc < 0)
              {
                close(sockfd);
                close(newfd);
                
                Err_sys("Server send")
              }
            }//send
                     
        }//switch 
        
      }//while read/write
   } //else if(pt == 0)
   else
     close(newfd);
 }//while accept
  close(sockfd);
  close(newfd);

  exit(EXIT_SUCCESS);
}
/***********************************************************************/

客戶端:

 #include "common.h"

int main(int argc, char **argv)
{
  int sockfd = -1;
  struct sockaddr_in server_addr;
  
  char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
  socklen_t addrlen = addrsize;
  
  int wc, rc;
  
  int maxfd;
  fd_set readfds;
  int ret = -1;
  struct timeval tv;
  
  if(argc != 5)
  {
    fprintf(stderr, "%s -p port -i ip/n", argv[0]);
    exit(EXIT_FAILURE);
  } 
  sockfd = socket(PF_INET, SOCK_STREAM, 0);
  if(sockfd == -1)
   Err_sys("Client socket")
   
  bzero(&server_addr, addrsize);
  server_addr.sin_family = PF_INET;
  server_addr.sin_addr.s_addr = inet_addr(argv[4]);
  server_addr.sin_port = htons(atoi(argv[2]));

  int count = 0; 
  while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
  {
    if(count++ <= 3)
    {
      fprintf(stderr, "Client is trying to connect.../n");
      sleep(3);
    }
    else
    {
      fprintf(stderr, "Client connects failurefully/n");
      close(sockfd); //shutdown(sockfd, SHUT_RDWR);
      exit(EXIT_FAILURE);
    }     
  }
  
  while(RUNNING)
  {
   
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    
    maxfd = sockfd;
    FD_ZERO(&readfds);
    FD_SET(0, &readfds);
    FD_SET(sockfd, &readfds);
    
    if((ret = select(maxfd + 1, &readfds, NULL, NULL, &tv)) == -1)
    {
      if(errno == EINTR)
        continue;
      close(sockfd);
      Err_sys("Client select")
    }
    else if(ret == 0)
    {
       //printf("Client timeout");
       continue;
    }
    else if(ret > 0)
    {
      if(FD_ISSET(0, &readfds))
      {
        memset(buffer_w, '/0', BUFFERSIZE);
    
        printf("[Client send]:");
        fflush(stdout);
        fgets(buffer_w, BUFFERSIZE, stdin);
        
        wc = send(sockfd, buffer_w, strlen(buffer_w), 0);
        if(wc < 0)
          Err_sys("Client send")
      }//send
      
      if(FD_ISSET(sockfd, &readfds))
      {
        memset(buffer_r, '/0', BUFFERSIZE);
        rc = recv(sockfd, buffer_r, BUFFERSIZE, 0);
        if(rc <= 0)
        {
          if(rc == 0)
          {
            FD_CLR(sockfd, &readfds);
            printf("Server has been closed/n");
          }
          close(sockfd);
          exit(EXIT_FAILURE);
        } 
        else
          printf("[Client recv]:%s/n", buffer_r);       
      }//recv    
    }    
  }//while
  
  close(sockfd);
  
  exit(EXIT_SUCCESS); 
}       
/***************************************************************/

TCP多線程併發網絡編程

/***************************************************************/  

服務器端:      
#include "common.h"

/*Thread function for reading and writing*/
void *rdwrthread(void *arg)
{
 
  char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
  int rc, wc;
  
  int outfd = *(int *)arg;
  fd_set readfds;
  int maxfd;
  struct timeval tv;
  int ret = -1;
  
  while(RUNNING)
  {
    maxfd = outfd;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    
    FD_ZERO(&readfds);
    FD_SET(0, &readfds);//FD_SET(STDIN_FILENO, &readfds);
    FD_SET(outfd, &readfds);
   
    ret = select(maxfd + 1, &readfds, NULL, NULL, &tv);
    switch(ret)
    {
      case -1:
        if(errno == EINTR)
          continue;
        Err_sys("Server select")
      case 0:
        //printf("Server timeout/n");
        continue;
      default:
        if(FD_ISSET(outfd, &readfds))
        {
          memset(buffer_r, '/0', BUFFERSIZE);
          rc = recv(outfd, buffer_r, BUFFERSIZE, 0);
          if(rc <= 0)
          {
            if(rc == 0)
            {
              FD_CLR(outfd, &readfds);  
              printf("Client has been closed/n");
            }
            close(outfd);
            pthread_exit(NULL);
          } 
          else
            printf("[Server recv]:%s/n", buffer_r);
        }//recv
        
        if(FD_ISSET(0, &readfds))
        {
          memset(buffer_w, '/0', BUFFERSIZE);
          printf("[Server send]:");
          fflush(stdout);
          
          fgets(buffer_w, BUFFERSIZE, stdin);  
          wc = send(outfd, buffer_w, strlen(buffer_w), 0);
          if(wc < 0)
          {
            close(outfd);     
            Err_sys("Server send")
          }
        }//send
                 
    }//switch 
    
  }//while read/write
   
  return NULL;
}

int main (int argc, char *argv[])
{
 
 int sockfd = -1, newfd  = -1;
 struct sockaddr_in server_addr, client_addr;
 socklen_t addrlen = addrsize;
 
 pthread_t pd;
 pthread_attr_t attr;

 sockfd = socket(PF_INET, SOCK_STREAM, 0);
 if(sockfd == -1)
  Err_sys("Server socket")
 
 bzero(&server_addr,  addrsize);
 server_addr.sin_family = PF_INET;
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
 server_addr.sin_port = htons(port);
 
 int i = 1;
 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use

 if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
 {
  close(sockfd);
  Err_sys("Server bind")
 }

 if(listen(sockfd, 10) == -1)
 {
  close(sockfd);
  Err_sys("Server listen")
 }

 pthread_attr_init(&attr);
 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
   
 while(RUNNING)
 {
    printf("Waiting a new connection/n");
    
    newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
    if(newfd == -1)
    {
      if(errno == EINTR)
        continue;
      
      pthread_attr_destroy(&attr);  
      Err_sys("Server accept")
    }
    else
      printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
   
    if(pthread_create(&pd, &attr, rdwrthread, (void *)&newfd) != 0)
    {
      close(newfd);
      close(sockfd);
      pthread_attr_destroy(&attr);
      Err_sys("Server pthread_create")
    }
    else
      fprintf(stdout, "Current master thread[%u] creates a new slave thread[%u]/n", pthread_self(), pd);
    
 }//while accept
  close(sockfd);
  close(newfd);
  
  pthread_attr_destroy(&attr);

   exit(EXIT_SUCCESS);
}
/****************************************************************/

客戶端:

 #include "common.h"

int main(int argc, char **argv)
{
  int sockfd = -1;
  struct sockaddr_in server_addr; //定義套接字結構體保持socket信息
  
  char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE]; //定義讀緩衝和寫緩衝
  socklen_t addrlen = addrsize;   //設置結構體大小
  
  int wc, rc;
  
  int maxfd;
  fd_set readfds;  //讀文件描述符集
  int ret = -1;
  struct timeval tv;  //時間結構體
  
  if(argc != 5)
  {
    fprintf(stderr, "%s -p port -i ip/n", argv[0]);
    exit(EXIT_FAILURE);
  }
  
  
  sockfd = socket(PF_INET, SOCK_STREAM, 0);  //建立socket連接
  if(sockfd == -1)
   Err_sys("Client socket")
   
  bzero(&server_addr, addrsize);   //設置sockaddr_in結構體中相關參數
  server_addr.sin_family = PF_INET;
  server_addr.sin_addr.s_addr = inet_addr(argv[4]);
  server_addr.sin_port = htons(atoi(argv[2]));

  int count = 0; //調用connect()函數主動發起對服務器端的連接
  while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
  {
    if(count++ <= 3)  //連接成功
    {
      fprintf(stderr, "Client is trying to connect.../n");
      sleep(3);
    }
    else   //連接失敗
    {
      fprintf(stderr, "Client connects failurefully/n"); 
      close(sockfd); //shutdown(sockfd, SHUT_RDWR);
      exit(EXIT_FAILURE);
    }
     
  }
  
  while(RUNNING)
  {
   
    tv.tv_sec = 1;  //設置多路複用超時時間1s
    tv.tv_usec = 0;
    
    maxfd = sockfd; 
    FD_ZERO(&readfds);  //清除一個文件描述符集
    FD_SET(0, &readfds);   //將標準輸入加入到讀文件描述符集
    FD_SET(sockfd, &readfds);    //將套接字文件描述符加入到讀文件描述符集
    
    if((ret = select(maxfd + 1, &readfds, NULL, NULL, &tv)) == -1)  //判斷文件描述符在1s內是否變化
    {
      if(errno == EINTR)   //遇到中斷的處理
        continue;
      close(sockfd);
      Err_sys("Client select")
    }
    else if(ret == 0)   //超時處理
    {
       //printf("Client timeout");
       continue;
    }
    else if(ret > 0)   //文件描述符集內有變化
    {
      if(FD_ISSET(0, &readfds))   //標準輸入文件描述符發生了變化
      {
        memset(buffer_w, '/0', BUFFERSIZE);
    
        printf("[Client send]:");
        fflush(stdout);
        fgets(buffer_w, BUFFERSIZE, stdin);  //獲取標準輸入的內容 存到緩衝區
        
        wc = send(sockfd, buffer_w, strlen(buffer_w), 0);  //發送消息給服務器端
        if(wc < 0)
          Err_sys("Client send")
      }//send
      
      if(FD_ISSET(sockfd, &readfds))  //sockfd文件描述符發生了變化
      {
        memset(buffer_r, '/0', BUFFERSIZE);
        rc = recv(sockfd, buffer_r, BUFFERSIZE, 0);  //收到服務器發來的消息
        if(rc <= 0)
        {
          if(rc == 0)
          {
            FD_CLR(sockfd, &readfds);  //將sockfd從文件描述符集中刪除
            printf("Server has been closed/n");
          }
          close(sockfd);  //關閉
          exit(EXIT_FAILURE);
        } 
        else
          printf("[Client recv]:%s/n", buffer_r);   //打印出內容    
      }//recv
      
      
    }
      
  }//while
  
  close(sockfd);  //關閉套接字
  
  exit(EXIT_SUCCESS);  //成功返回
}      
       
       
       
       
       
       
               
        
        
        
        
              
        
        
       

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章