Linux TCP server 只能接受一個 TCP 連接


#include <stdio.h>

#include <sys/types.h> 
#include <sys/socket.h> 

#include <string.h> // menset 函數
#include <stdlib.h> // exit 函數

#include<netinet/in.h> // struct sockaddr_in 結構類型

#include<arpa/inet.h> // inet_ntoa 函數

#include <unistd.h> // close 函數

int tcpServerInit( void );

void main()
{
    //2017年11月28日11:18:18,suozhang,add
    printf("2017年11月28日11:18:39,hello,world!\r\n");
    
    tcpServerInit();

}


int tcpServerInit( void )
{
      // AF_INET     : IPV4網絡協議 
      // SOCK_STREAM : 提供雙向連續且可信賴的數據流,即TCP,支持OOB機制,在所有數據傳輸前必須使用connect()來建立連接狀態
      // 0           : 用來指定socket所使用的傳輸協議編號,通常此參考不用管他,設為0即可
      int tcpServerSocket = socket(AF_INET, SOCK_STREAM, 0);
      
      if(tcpServerSocket < 0)  
      {  
          // 創建 socket 失敗
          // perror(s) 用來將上一個函數發生錯誤的原因輸出到標准設備(stderr)。
          perror("new tcpServerSocket error is ");
          
          //exit(-1)表示程序異常退出
          exit(-1);
      }
      
      //定義 服務器 IP地址和端口號 結構體變量
      struct sockaddr_in tcpServerAddr;
      
      //將結構體清空
      memset(&tcpServerAddr,0,sizeof(tcpServerAddr));
      
      tcpServerAddr.sin_family = AF_INET;  // AF_INET : IPV4網絡協議 
      
      // htons() 函數用來將 16位 類型 轉換為 網絡字符順序
      tcpServerAddr.sin_port = htons(9527);// 綁定端口號為9527,通常是大於1024的一個值
      
      // inet_addr() 函數用來將IP地址字符串轉換成網絡所使用的二進制數字
      tcpServerAddr.sin_addr.s_addr = inet_addr("10.1.51.53");// 這里可填寫 INADDRY_ANY 表示服務器自動填充本機IP地址
      
      if( bind(tcpServerSocket, (struct sockaddr*)&tcpServerAddr, sizeof(tcpServerAddr)) < 0 )   
      {               
           //綁定失敗
           perror("bind tcpServerSocket err is ");
           
           close( tcpServerSocket ); //綁定失敗,因此關閉創建的 socket
           
           //exit(-1)表示程序異常退出
           exit(-1);
      }   
      
      
              printf("TCP server ip: %s  and port: %d.\r\n", inet_ntoa(tcpServerAddr.sin_addr), ntohs(tcpServerAddr.sin_port));  
              
              
  
      //監聽socket ,第二個參數規定了內核應該為相應套接口排隊的最大連接個數。  
      if( listen(tcpServerSocket, 5) < 0)  
      {  
           //監聽失敗  
           perror("listen tcpServerSocket err is ");
           
           close( tcpServerSocket ); //綁定失敗,因此關閉創建的 socket
           
           //exit(-1)表示程序異常退出
           exit(-1);
      }
      

      
        
      struct sockaddr_in tcpClientAddr;
      
      //將結構體清空
      memset(&tcpClientAddr,0,sizeof(tcpClientAddr));
      
      socklen_t tcpClientAddrLen = sizeof(struct sockaddr);
      
      // accept() 函數 接受遠程計算機的連接請求,建立與客戶機之間的通信連接。
      // 服務器處於監聽狀態時,如果某時刻獲得客戶機的連接請求,此時並不是立即處理這個請求,
      // 而是將這個請求放在等待隊列中,當系統空閑時再處理客戶機的連接請求。
      // 重點: 當 accept() 函數接受一個連接時,會返回一個新的socket標識符,
      // 以后的數據傳輸和讀取就要通過這個新的socket編號來處理,
      // 原來參數的socket(這里指 tcpServerSocket )也可以繼續使用,繼續監聽其他客戶機的連接請求
      // 因此 服務器跟一個客戶端連接成功,就會產生兩個套接字,一個當初自己創建的,一個 accept() 創建的
      
      int tcpClientSocket = accept(tcpServerSocket, (struct sockaddr*)&tcpClientAddr, &tcpClientAddrLen);

      if( tcpClientSocket < 0 )  
      {  
           perror("accept tcpServerSocket err is ");  
          
           close( tcpServerSocket ); //綁定失敗,因此關閉創建的 socket
           
           //exit(-1)表示程序異常退出
           exit(-1);
      }  
      else  
      {  
          printf("connected with ip: %s  and port: %d.\r\n", inet_ntoa(tcpClientAddr.sin_addr), ntohs(tcpClientAddr.sin_port));  
      } 
      
      char buf[1024] ={ 0 };
      
      for( ;; )
      {
          if( recv( tcpClientSocket, buf, sizeof( buf ),0 ) < 0 )
          {
               perror("recv tcpClientSocket err is ");  
              
               close( tcpServerSocket ); //綁定失敗,因此關閉創建的 socket
               
               close( tcpClientSocket ); //綁定失敗,因此關閉創建的 socket
               
               //exit(-1)表示程序異常退出
               exit(-1);
          }
          
          printf("接收的數據是:%s.\r\n",buf);
          
          //將接收的數據發回客戶端
          if( send( tcpClientSocket,buf,strlen(buf),0 ) < 0 )
          {
               perror("send tcpClientSocket err is ");  
              
               close( tcpServerSocket ); //綁定失敗,因此關閉創建的 socket
               
               close( tcpClientSocket ); //綁定失敗,因此關閉創建的 socket
               
               //exit(-1)表示程序異常退出
               exit(-1);
          }
          
          //將接收緩沖區清空
          memset(buf,0,sizeof(buf));
          
      }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM