day_15_socket模型、TCP模型

一、基於socket的一對一通信模型

1.1 相關函數的解析

(1)socket()

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

功能:
  主要用於創建用於交流 / 通信的端點;

參數:
  第一個參數:協議族/域,決定了本地通信還是網絡通信;
    AF_UNIX / AF_LOCAL - - - - - 表示實現本地通信
    AF_INET - - - - - - - - - - - - - - - -表示實現基於IPv4的網絡通信
  第二個參數:具體的通信類型,決定了具體的通信協議;
    SOCK_STREAM - - - - 提供有序的、可靠的、雙向的、面向連接的字節流通信方式,也就是基於TCP協議的通信方式
    SOCK_DGRAM - - - - - 提供不可靠的,非面向連接的數據報通信方式,也就是基於UDP協議的通信方式
  第三個參數:具體的特殊協議,默認給0即可;

返回值:
  success —- 文件描述符,error —- -1;

(2)通信地址的常用地址數據類型

  a. struct sockaddr類型 - - - - 主要用於函數的形參類型,基本不會定義結構體變量去使用;

struct sockaddr
{
    sa_family_t  sa_family;
    char        sa_data[14];
}

  b. struct sockaddr_un類型 - - - - 主要用於實現本地通信;

#include <sys/un.h>
struct sockaddr_un
{
    sa_family_t    sun_family;  //協議族,和socket()的第一個實參保持一致即可;
    char           sun_path[];  //socket文件的路徑名;
}

  c. struct sockaddr_in類型 - - - - 主要用於網絡通信;

#include <netinet/in.h>
struct sockaddr_in
{
    sa_family_t         sin_family;  //協議族 AF_INET
    in_port_t           sin_port;    //端口號
    struct in_addr       sin_addr;    //IP地址
}
struct in_addr
{
    in_addr_t    s_addr;  //整數類型的IP地址
}

(3)bind()

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:
  主要用於綁定socket和指定的通信地址;

參數:
  第一個參數:socket的描述符,socket()的返回值;
  第二個參數:結構體指針,用於指定通信地址,需要進行類型轉換;
  第三個參數:通信地址的大小,使用sizeof()計算即可;

(4)connect()

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:
  主要用於建立socket到通信地址的連接,參數和返回值參考bind()即可;

(5)字節序轉換函數

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
/* 主要用於將32位二進制組成的主機字節序轉換爲網絡字節序 */
uint16_t htons(uint16_t hostshort); 
/* 主要用於將16位二進制組成的主機字節序轉換爲網絡字節序 */
uint32_t ntohl(uint32_t netlong);
/* 主要用於將32位二進制組成的網絡字節序轉換爲主機字節序 */
uint16_t ntohs(uint16_t netshort);
/* 主要用於將16位二進制組成的網絡字節序轉換爲主機字節序 */

(6)IP地址的轉換函數

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);

功能:
  主要用於將字符串形式的IP地址轉換爲整數類型的IP地址;

char *inet_ntoa(struct in_addr in);

功能:
  主要用於將結構體類型的IP地址轉換爲字符串類型;

二、基於TCP協議的網絡通信模型

2.1 通信模型

服務器:
 (1)創建socket,使用socket();
 (2)準備通信地址,使用結構體類型;
 (3)綁定socket和通信地址,使用bind();
 (4)監聽,使用listen();
 (5)響應客戶端的連接請求,使用accept();
 (6)進行通信,使用send()/recv();
 (7)關閉socket,使用close();

客戶端:
 (1)創建socket,使用socket();
 (2)準備通信地址,使用服務器的地址;
 (3)連接socket和通信地址,使用connect();
 (4)進行通信,使用send()/recv();
 (5)關閉socket,使用close();

2.2 相關函數的解析

(1)listen()

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);

功能:
  主要用於將參數sockfd所指定的socket標記爲被動的socket,也就是原來的socket是可以用於通信的,但是標記爲被動的socket之後,專門用於響應即將到來的連接請求,不再用於通信;

參數:
  第一個參數:socket描述符,socket()的返回值;
  第二個參數:主要用於指定懸而未決連接請求隊列的最大長度,當該隊列爲滿時,有客戶端發來連接請求,則會被拒絕;

(2)accept()

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

功能:
  主要用於響應指定socket上面的一個連接請求;該函數會提取懸而未決連接請求隊列中的第一個連接請求進行響應,響應的方式就是再創建一個連接好的socket進行通信;

參數:
  第一個參數:socket的描述符,socket()的返回值;
  第二個參數:結構體指針,用於帶出客戶端的通信地址;
  第三個參數:指針類型,用於帶出客戶端通信地址的大小;

返回值:
  success —- 通信socket的描述符,error —- -1;

(3)send()

#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

功能:
  主要用於向指定的socket發送指定的數據內容;

參數:
  第一個參數:socket描述符,用於通信的socket;
  第二個參數:被髮送數據的首地址;
  第三個參數:被髮送數據的大小;
  第四個參數:發送的標誌,默認給0即可;

返回值:
  success —- 實際發送數據大小,error —- -1;

(4)recv()

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

功能:
  主要用於接收參數指定socket中的數據;

參數:
  第一個參數:socket描述符,用於通信的socket;
  第二個參數:存放接收到數據的緩衝區首地址;
  第三個參數:期望接收的數據大小;
  第四個參數:接收的標誌,默認給0即可;

返回值:
  success —- 實際接收數據大小,error —- -1;

練習:
  使用基於tcp協議的通信模型實現一對多通信
   a. 要求服務器可以不斷地響應客戶端的連接請求;
    => 使用while(1)無限循環
   b. 要求服務器可以同時接收多個客戶端發來的消息;
    => 使用fork()創建子進程
   c. 要求服務器可以和每一個客戶端不斷進行通信;
    => 使用while(1)無限循環
   d. 要求當客戶端發來”bye”時,表示客戶端下線;
    => 使用strcmp()比較
   e. 要求客戶端發送的消息由鍵盤輸入;
    => 使用scanf()/gets()/fgets()
   f. 要求關閉服務器請按ctrl+c來實現;
    => 對信號SIGINT進行自定義處理

明日預報:
 (1)網絡編程;
 (2)多線程;

發佈了50 篇原創文章 · 獲贊 48 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章