Linux系統下socket編程socket接口介紹(二)

2021-02-20 txp玩Linux

函數介紹

- 發送和接收 -

(1)send和write:

首先說明的一點,之前介紹的socket這個函數,非常類似我們之前介紹的open函數,他們都會返回一下文件描述符;所以這裡的send函數和write函數作用類似,我們用man手冊來查看它的具體形式和用法:

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

   ssize_t send(int sockfd, const void *buf, size_t len, int flags);

說明:

         第一個參數sockfd就是socket函數返回的文件描述符;第二個參數指向發送的信息所在的緩衝區(內存);第三個參數指緩衝區的長度大小;第四個參數一般設置為0(如果不是這種情況,可以具體再查看)。不論是客戶還是伺服器應用程式都用send函數來向TCP連接的另一端發送數據。客戶程序一般用send函數向伺服器發送請求,而伺服器則通常用send函數來向客戶程序發送應答。

(2)recv和read:

函數recv和之前介紹的read函數的用法差不多,我們還是用man手冊來查看一它的形式和用法:

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

   ssize_t recv(int sockfd, void *buf, size_t len, int flags);

說明:

 

       這裡面的參數和上面send的參數說明一樣。不論是客戶還是伺服器應用程式都用recv函數從TCP連接的另一端接收數據。

- IP位址格式轉換函數 -


(1)inet_aton、inet_addr、inet_ntoa(只用IPV4的IP位址),現在用的比較少,不過大多程序裡面會看到這些函數,所以還是要學習一下它的作用,老方法使用man手冊來查看它的形式和用法:

   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>

   int inet_aton(const char *cp, struct in_addr *inp);

   in_addr_t inet_addr(const char *cp);

   in_addr_t inet_network(const char *cp);

   char *inet_ntoa(struct in_addr in);

   struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);

   in_addr_t inet_lnaof(struct in_addr in);

   in_addr_t inet_netof(struct in_addr in);

說明:

  

        首先我們來看inet_aton函數,它轉換網絡主機地址ip(如192.168.1.10)為二進位數值,並存儲在struct in_addr結構中,即第二個參數*inp,函數返回非0表示cp主機有地有效,返回0表示主機地址無效。(這個轉換完後不能用於網絡傳輸,還需要調用htons或htonl函數才能將主機字節順序轉化為網絡字節順序,這兩個函數先不講,實戰遇到的話,再進行解析),具體可以看下面Linux的源文:

 inet_aton()  converts  the  Internet  
host  address  cp  from  the  IPv4  
numbers-and-dots notation into binary 
form (in network byte order) and stores it in the 
 structure that inp points to.
   inet_aton() returns nonzero if the address is valid, 
   zero if not.  The address 
 supplied in cp can have one of the following forms:

   a.b.c.d   Each of the four numeric parts specifies a 
  byte of the address; the 
 bytes are assigned in left-to-right order to produce the binary address.

   a.b.c     Parts a and b specify the first two bytes of the binary address.  Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address.  This  notation
             is suitable for specifying (outmoded) Class B network addresses.

   a.b       Part a specifies the first byte of the binary address.  Part b is 
  interpreted as a 24-bit value that defines the
  rightmost three bytes of the binary address.  This notation is suit‐
             able for specifying (outmoded) Class A network addresses.

   a         The value a is interpreted as a 32-bit value that is stored 
   directly into the binary address without any byte rearrangement.

   In all of the above forms, components of the dotted address can be specified
    in decimal, octal (with a leading 0), or hexadecimal, with a leading 0X). 
    Addresses in any  of  these  forms  are
   collectively termed IPV4 numbers-and-dots notation.  The form that uses exactly
    four decimal numbers is referred to as IPv4 dotted-decimal notation (or sometimes: IPv4 dotted-quad notation).

   inet_aton() returns 1 if the supplied string was successfully interpreted, 
  or 0 if the string is invalid (errno is not set on error).

接著是inet_addr函數,它的作用主要是轉換網絡主機地址(如192.168.1.10)為網絡字節序二進位值,如果參數char *cp無效,函數回-1(INADDR_NONE),這個函數在處理地址為255.255.255.255時也返回-1,255.255.255.255是一個有效的地址,不過inet_addr無法處理:

   The  inet_addr()  function converts the Internet 
   host address cp from IPv4 numbers-and-dots notation into 
   binary data in network byte order.  
   If the input is invalid, INADDR_NONE (usually -1)
   is returned.  
   Use of this function is problematic because -1 is a 
 valid address (255.255.255.255). 
   Avoid its use in favor of inet_aton(), inet_pton(3), 
  or  getaddrinfo(3),  which  provide  a
   cleaner way to indicate error return.

最後就是inet_ntoa函數,它的作用主要是轉換網絡字節排序的地址為標準的ASCII以點分開的地址,該函數返回指向點分開的字符串地址(如192.168.1.10)的指針,該字符串的空間為靜態分配的,這意味著在第二次調用該函數時,上一次調用將會被重寫(復蓋),所以如果需要保存該串最後複製出來自己管理!

 The inet_ntoa() function converts the Internet host 
 address in, given in network byte order, to a string in 
 IPv4 dotted-decimal notation.  The string is returned  
 in  a  statically  allocated
   buffer, which subsequent calls will overwrite.

(2)inet_ntop、inet_pton,這兩個函數是隨IPv6出現的函數,對於IPv4地址和IPv6地址都適用,函數中p和n分別代表表達(presentation)和數(numeric)。地址的表達格式通常是ASCII字符串,數值格式則是存放到套接字地址結構的二進位值。我們還是用man手冊來查看的它們的形式和作用:

  #include <arpa/inet.h>

   const char *inet_ntop(int af, const void *src,  char *dst, socklen_t size);


 我們先來看inet_ntop這個函數,第一個參數表示地址族(就是ipv4和ipv6),它的作用是把二進位格式轉化為點分十進位的ip地址格式;inet_ntop函數的dst參數不可以是一個空指針。調用者必須為目標存儲單元分配內存並指定其大小,調用成功時,這個指針就是該函數的返回值。size參數是目標存儲單元的大小,以免該函數溢出其調用者的緩衝區。如果size太小,不足以容納表達式結果,那麼返回一個空指針,並置為errno為ENOSPC:

   This  function  converts  the  network address 
   structure src in the af address family into a 
   character string.  The resulting string is copied to 
   the buffer pointed to by dst, which must be a
   non-null pointer.  The caller specifies the number of 
   bytes available in this buffer in the argument size.

   inet_ntop() extends the inet_ntoa(3) function to 
   support multiple address families, inet_ntoa(3) is 
   now considered to be deprecated in favor of 
   inet_ntop().  The  following  address  families
   are currently supported:

   AF_INET
          src  points  to a struct in_addr (in network 
   byte order) which is converted to an IPv4 network 
  address in the dotted-decimal format, 
  "ddd.ddd.ddd.ddd".  The buffer dst must be at least
          INET_ADDRSTRLEN bytes long.

   AF_INET6
          src points to a struct in6_addr (in network 
   byte order) which is converted to a representation of 
   this address in the most appropriate IPv6 network 
   address  format  for  this  address.
          The buffer dst must be at least 
 INET6_ADDRSTRLEN bytes long.

 RETURN VALUE
   On success, inet_ntop() returns a non-null pointer to 
  dst.  NULL is returned if there was an error, with 
  errno set to indicate the error.

ERRORS
   EAFNOSUPPORT
          af was not a valid address family.

   ENOSPC The converted address string would exceed the 
   size given by size.

接著我們來看inet_pton函數,它的作用主要是將點分十進位的ip地址轉化為二進位格式:


  #include <arpa/inet.h>

   int inet_pton(int af, const char *src, void *dst);

DESCRIPTION
   This  function  converts  the character string src 
  into a network address structure in the af address 
  family, then copies the network address structure to 
  dst.  The af argument must be either
   AF_INET or AF_INET6.  dst is written in network byte 
  order.

   The following address families are currently 
supported:

   AF_INET
          src points to a character string containing an 
  IPv4 network address in dotted-decimal format, 
  "ddd.ddd.ddd.ddd", where ddd is a decimal number of up 
  to three digits in the range  0  to
          255.  The address is converted to a struct 
  in_addr and copied to dst, which must be sizeof(struct 
  in_addr) (4) bytes (32 bits) long.

   AF_INET6
          src  points to a character string containing 
   an IPv6 network address.  The address is converted to 
   a struct in6_addr and copied to dst, which must be 
   sizeof(struct in6_addr) (16) bytes
          (128 bits) long.  The allowed formats for IPv6 
   addresses follow these rules:

          1. The preferred format is x:x:x:x:x:x:x:x.  
   This form consists of eight hexadecimal numbers, each 
   of which expresses a 16-bit value (i.e., each x can 
   be up to 4 hex digits).

          2. A series of contiguous zero values in the 
   preferred format can be abbreviated to ::.  Only one 
   instance  of  ::  can  occur  in  an  address.   For  
   example,  the  loopback  address
             0:0:0:0:0:0:0:1 can be abbreviated as ::1.  
   The wildcard address, consisting of all zeros, can be 
  written as ::.

          3. An  alternate  format  is useful for 
 expressing IPv4-mapped IPv6 addresses.  This form is 
 written as x:x:x:x:x:x:d.d.d.d, where the six leading 
 xs are hexadecimal values that define
             the six most-significant 16-bit pieces of 
 the address (i.e., 96 bits), and the ds express a value 
 in dotted-decimal notation that defines  the  least  
 significant  32  bits  of  the
             address.  An example of such an address is 
 ::FFFF:204.152.189.116.

          See RFC 2373 for further details on the 
 representation of IPv6 addresses.

RETURN VALUE
   inet_pton()  returns 1 on success (network address 
 was successfully converted).  0 is returned if src does 
 not contain a character string representing a valid 
 network address in the specified
   address family.  If af does not contain a valid 
 address family, -1 is returned and errno is set to 
EAFNOSUPPORT.

- 表示IP位址相關數據結構 -

(1)上面的一些函數參數裡面用到的結構體(比如bind函數參數裡的const struct sockaddr *addr等)都定義在 netinet/in.,我們可以用 vim  /usr/include/netinet/in.h 來查看,這裡具體的我就不理出來了,裡面的內容比較多。

(2)struct  sockaddr,這個結構體是linux的網絡編程接口中用來表示IP位址的

標準結構體,bind、connect等函數中都需要這個結構體,這個結構體是兼容IPV4和IPV6的。在實際編程中這個結構體會被一個struct sockaddr_in或者一個struct sockaddr_in6所填充。

(3)typedef  uint32_t   in_addr_t:網絡內部用來表示IP位址的類型。

(4)struct in_addr
 {
      in_addr_t s_addr;
  };
(5)struct sockaddr_in
 {
     __SOCKADDR_COMMON (sin_);
     in_port_t  sin_port;                 /* Port number.  */
    struct in_addr sin_addr;            /* Internet address.  */

/* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
                       __SOCKADDR_COMMON_SIZE -
                       sizeof (in_port_t) -
                       sizeof (struct in_addr)];
   };

今天主要是介紹了一下函數用法,下一篇文章開始進入實戰講解!

關注公眾號,每周分享至少3篇開源技術乾貨,文章中如有沒看懂的地方可以私聊我,我看到了會立馬回覆你,個人微信號:a18879499804

相關焦點

  • Linux C Socket Api詳解
    UNIX 環境高級編程對Socket通信的描述是套接字網絡IPC(進程間通信),可以用於計算機間通信也可用於計算機內通信,管道、消息隊列、信號量以及共享內存等都是屬於計算機內通信的情況。一、 套接字Api詳細介紹1. 套接字描述符首先會先到的是文件描述符,對Linux一切皆文件的哲學又多懂了一點兒點兒。套接字是通信端點的抽象。
  • PHP SOCKET編程
    特別是php的socket擴展庫可以做的事情簡直不會比c差多少。php的socket連接函數1、集成於內核的socket這個系列的函數僅僅只能做主動連接無法實現埠監聽相關的功能。而且在4.3.0之前所有socket連接只能工作在阻塞模式下。
  • 基於Socket的java通信編程詳解
    32位二進位  5、埠  區分一臺主機的多個不同應用程式,埠號範圍為0-65535,其中0-1023位為系統保留。    二、InetAddress  InetAddress類用於標識網絡上的硬體資源,標識網際網路協議(IP)地址。
  • Java socket編程
    而TCP層則提供面向應用的可靠(tcp)的或非可靠(UDP)的數據傳輸機制,這是網絡編程的主要對象,一般不需要關心IP層是如何處理數據的。目前較為流行的網絡編程模型是客戶機/伺服器(C/S)結構。即通信雙方一方作為伺服器等待客戶提出請求並予以響應。客戶則在需要服務時向伺服器提 出申請。
  • 網絡編程基礎學習筆記2:socket接口及網絡編程三要素
    對於網絡編程而言,由於其底層語言是通過C語言來實現的,所以建議在學習的時候使用C語言來進行學習!網絡編程中常用的socket接口如下:socket()接口,用於創建socket;bind():用於綁定socket到本地地址和埠,通常由服務端調用(客戶端一般直接由connect直接主動去連結服務端);listen():用於開啟監聽模式,TCP專用;accept():用於伺服器等待客戶端連接,該情況一般在阻塞狀態下產生
  • 簡單說說Python Socket編程步驟?
    廢話不多說,開始今天的題目:問:簡單說說Python socket編程步驟?答:Socket是應用層與TCP/IP協議族通信的中間軟體抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。所以,我們無需深入理解tcp/udp協議,socket已經為我們封裝好了,我們只需要遵循socket的規定去編程,寫出的程序自然就是遵循tcp/udp標準的。
  • Linux C語言高級編程之Socket網絡編程!
    Socket網絡編程網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個
  • Python網絡編程socket模塊實例解析
    socket就是該模式的一個實現,socket即是一種特殊的文件,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉)。(1)利用socket進行簡單的連結Python裡面的socket支持UDP、TCP、以及進程間的通信,socket可以把我們想要發送的東西封裝起來,發送過去,然後反解成原來的樣子,事實上網路通信可以理解成都是建立在socket之上,下面的代碼是演示利用socket進行簡單的連結#要成一次通信,至少要有兩個人,也就是一個服務端
  • PHP編寫基本的Socket程序
    我的目的因為在以後的學習中,我可能會用到網絡方面的內容,但同時很多寫 PHP 的 coder 都沒寫過 socket 程序,但是肯定聽說過它,也肯定聽說過網絡編程這個詞;所以為了今後的學習,我打算在這裡先簡單的講解下相關知識,本篇博文自帶實例程序,代碼託管在碼云:php-socket-base-code
  • 門禁系統socket通訊編程
    ); // $socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname("udp")); // 創建Socket if (socket_connect($socket, "192.168.16.254", 8080)) { //連接 for ($j = 0; $j < count($sendStrArray); $j++) { socket_write
  • python socket實戰(二)
    每周一總結,準時為你充電上周講了1和2部分,這周接著講3和4,希望給以後用到socket編程的同學一些參考。這個在c語言編程中尤為常見。例如,有一個如下到結構體,python如何用socket進行通信傳遞該消息呢。
  • Socket網絡編程核心API深入分析(一):bind函數
    注意:本片文章涉及到的內核源碼來自linux內核版本3.6簡單的伺服器與客戶端實現本篇文章的重點在於從底層深入分析bind()函數,相信已經能夠自己實現一個簡單的伺服器和客戶端並進行交互,下面是一個簡單的demo,幫助大家複習一下socket編程api的調用過程。
  • 從socket到TCP協議,透徹理解網絡編程
    這裡我們首先重點介紹2個概念,一個概念是網絡編程,另外一個是協議。我們知道網絡協議是一個分層的協議族,也就是是有一組協議構成,從下往上各自負責各自的功能。那什麼是協議呢?協議的字面意思是共同計議,商議。簡單的理解其實就是多方進行溝通的規定。而網絡協議其實就是在網絡中多個計算節點進行交互、溝通的規定。如果根我們日常生活對比的話,協議可以理解為語言,比如漢語普通話。
  • 巧用 Curl 命令測試 Unix Socket 接口
    經常遇到一些監聽地址不是 IP:Port 而是 Unix Socket 的程序,這些程序如果使用的是 HTTP 協議,Unix Socket 接口也可以用}用 curl 訪問它的 Unix Socket 的方法如下:$ curl --unix-socket /tmp/nginx-status-server.sock http://localhost/nginx_statusActive connections
  • 網絡編程基礎之Socket概述
    概念Socket接口是TCP/IP網絡的API,通過此接口,可以開發TCP/IP網絡上的應用程式。Socket接口是一種特殊的I/O,也是一種文件描述符。我們調用類似於打開文件的函數打開Socket,會返回一個Socket描述符。
  • Python Socket 編程學習筆記
    埠:光有IP位址是不夠的,埠是識別一個IP位址下的具體進程,比如,web服務的標準埠是80,SMTP是25,FTP是21。埠號小於1024的是internet標準服務的埠,大於1024的可以任意使用。
  • Windows編程技術:Socket通信(上)
    Socket翻譯成中文就是「套接字」的意思,所謂的Socket編程就是指用計算機語言通過編程來實現計算機之間的通信問題。Socket通信技術即就是兩臺聯網或者多臺聯網的計算機之間的數據交換技術,這就涉及著通信端的協議等等問題。
  • 懶人入門網絡編程(四):實現一個socket長連接沒那麼簡單!
    在Java的SDK中,socket共有兩個接口,一個是用於監聽連結請求的ServerSocket和用於端與端通信的sockect,至於這兩個socket的區別在後面解釋。單獨開一個線程專門處理服務端數據的接收即可,你如果想進一步完善這個功能,可以自己嘗試一下,或者後面我要說的socket長連接實現了這一點你可以進行參考。值得關注的是我們在進行網絡編程的過程中要特別注意異常的處理,當發生異常的時候,我們要關閉socket。
  • socket編程基礎,從了解到實現
    java生下來一開始就是為了計算機之間的通信,因此這篇文章也將開始介紹一下java使用socket進行計算機之間的通信,在上一篇文章中已經對網絡通信方面的基礎知識進行了總結,這篇文章將通過代碼案例來解釋說明。
  • Java socket通信基本原理介紹
    Java socket通信基本原理介紹 Java socket通信在不斷的進行相關代碼的開發,下面我們就看看如何才能更好的使用有關技術為我們的編程工作帶來一定的幫助。