socket主要函數說明

 

1.   基本套接字函數

(1)socket函數原型

socket(建立一個socket文件描述符)

所需頭文件

#include <sys/types.h>       

#include <sys/socket.h>

函數說明

建立一個socket文件描述符

函數原型

int socket(int domain, int type, int protocol)

函數傳入值

domain

AF_INET:IPv4協議

AF_INET6:IPv6協議

AF_LOCAL:Unix域協議

AF_ROUTE:路由套接口

AF_KEY:密鑰套接口

type

SOCKET_STREAM:雙向可靠數據流,對應TCP

SOCKET_DGRAM:雙向不可靠數據報,對應UDP

SOCKET_RAW:提供傳輸層以下的協議,可以訪問內部網絡接口,例如接收和發送ICMP報文

protocol

type爲SOCKET_RAW時需要設置此值說明協議類型,其他類型設置爲0即可

函數返回值

成功:socket文件描述符

失敗:-1,失敗原因存於error中

 

表18-1列出了當進行socket調用時,中協議簇(domain)與類型(type)可能產生的組合。

表18-1 socket中協議簇(domain)與類型(type)組合表

 

AF_INET

AF_INET6

AF_LOCAL

AF_ROUTE

AF_KEY

SOCK_STREAM

TCP

TCP

Yes

 

 

SOCK_DGRAM

UDP

UDP

Yes

 

 

SOCK_RAW

IPv4

IPv6

 

Yes

Yes

 

(2)bind函數原型

bind(將一個本地協議地址與socket文件描述符聯繫起來)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

將一個協議地址與socket文件描述符聯繫起來

函數原型

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

函數傳入值

sockfd

socket文件描述符

addr

my_addr指向sockaddr結構,該結構中包含IP地址和端口等信息

addrlen

sockaddr結構的大小,可設置爲sizeof(struct sockaddr)

函數返回值

成功:0

失敗:-1,失敗原因存於error中

利用bind函數綁定地址時,可以指定IP地址和端口號,也可以指定其中之一,甚至一個也不指定。可以使用通配地址INADDR_ANY(爲宏定義,其值等於0),它通知內核選擇IP地址。表18-2列出了設置socket地址結構的幾種方式,但在實際中,綁定的端口號都需要指定。

         表18-2 設置socket地址結構的幾種方式       

進程指定

說 明

IP地址

端口

通配地址INADDR_ANY

0

內核自動選擇IP地址和端口號

通配地址INADDR_ANY

非0

內核自動選擇IP地址,進程指定端口號

本地IP地址

0

進程指定IP地址,內核自動選擇端口號

本地IP地址

非0

進程指定IP地址和端口號

 

(3)listen函數原型

listen (等待連接)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

等待連接

函數原型

int listen(int sockfd, int backlog)

函數傳入值

sockfd

監聽socket文件描述符

backlog

套接字排隊的最大連接個數

函數返回值

成功:0

失敗:-1,失敗原因存於error中

特別說明

對於監聽socket文件描述符sockfd,內核要維護兩個隊列,分別爲未完成連接隊列和已完成連接隊列,這兩個隊列之和不超過backlog

 

(4)connect函數原型

connect(建立socket連接)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

建立socket連接

函數原型

int connect(int sockfd, const struct sockaddr *serv_addr,

                   socklen_t addrlen)

函數傳入值

sockfd

socket文件描述符

serv_addr

連接的網絡地址和端口

addrlen

sockaddr結構的大小,可設置爲sizeof(struct sockaddr)

函數返回值

成功:0

失敗:-1,失敗原因存於error中

附加說明

函數connect激發TCP的三路握手過程,出錯返回有以下幾種情況:

①     如果客戶沒有收到SYN分節的響應(總共75秒,這之間可能重發了若干次SYN),則返回ETIMEDOUT

②     如果對客戶的SYN的響應是RST,則表明該服務器主機在指定的端口上沒有進程在等待與之相連,函數返回錯誤ECONNREFUSED

③     如果客戶發出的SYN在中間路由器上引發一個目的地不可達的ICMP錯誤,內核返回EHOSTUNREACH或ENETUNREACH錯誤(即ICMP錯誤)給進程

 

(5)accept函數原型

                accept(接受socket連接)

 

 

所需頭文件

#include <sys/types.h>     

#include <sys/socket.h>

函數說明

接受socket連接,返回一個新的socket文件描述符,原socket文件描述符仍爲listen函數所用,而新的socket文件描述符用來處理連接的讀寫操作

函數原型

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

函數傳入參數

sockfd: socket文件描述符

addrlen:addr的大小,可設置爲sizeof(struct sockaddr)

函數傳出參數

addr:填入遠程主機的地址數據

函數返回值

成功:實際讀取字節數

失敗:-1,錯誤代碼存放在error中

附加說明

①     accept函數由TCP服務器調用,爲阻塞函數,從已完成連接的隊列中返回一個連接;如果該對列爲空,則進程進入阻塞等待

②     函數返回的套接字爲已連接套接字,而監聽套接字仍爲listen函數所用

 

(6)close函數原型

close (關閉連接的socket文件描述符)

所需頭文件

#include <unistd.h>

函數說明

關閉連接的socket文件描述符

函數原型

int close(int sockfd)

函數傳入值

sockfd:socket文件描述符

函數返回值

成功:0

失敗:-1,失敗原因存於error中

附加說明

①     close函數默認功能是將套接字置爲“已關閉”標記,並立即返回給進程,這個套接字不能再爲該進程所用

②     正常情況下,close將引發四個分節終止序列,但在終止前將發送已排隊的數據

③     如果套接字描述符訪問計數在調用close後大於0(多個進程共享同一個套接字的情況下),則不會引發TCP終止序列(即不會發送FIN分節)

 

(7)shutdown函數原型

shutdown(終止socket通信)

所需頭文件

#include <sys/socket.h>

函數說明

終止socket通信

函數原型

int shutdown(int s, int how)

函數傳入值

s

socket文件描述符

how

0(SHUT_RD):關閉socket連接的讀這一半,不再接收套接字中的數據且現留在收緩衝區的數據作廢

1(SHUT_WR):關閉socket連接的寫這一半(半關閉),但留在套接字發送緩衝區中的數據都會被髮送,後跟TCP連接終止序列,不管訪問計數是否大於0,此後將不能再執行對套接字的任何寫操作

2(SHUT_RDWR):socket連接的讀、寫都關閉

函數返回值

成功:0

失敗:-1,失敗原因存於error中

 

(8)read函數原型

                read(從打開的socket文件流中讀取數據)

 

 

所需頭文件

#include <unistd.h>

函數說明

從打開的socket文件流中讀取數據,這裏僅說明此函數應用於socket的情況

函數原型

ssize_t read(int fd, void *buf ,size_t count)

函數傳入參數

fd: socket文件描述符

count:最大讀取字節數

函數傳出參數

buf:讀取數據的首地址

函數返回值

成功:實際讀取字節數

失敗:-1,錯誤代碼存放在error中

附加說明

調用函數read從socket文件流中讀取數據時,有如下幾種情況:

①     套接字接收緩衝區接收數據,返回接收到的字節數

②     TCP協議收到FIN數據,返回0

③     TCP協議收到RST數據,返回-1,同時errno設置爲ECONNRESET

④     進程阻塞過程中接收到信號,返回-1,同時errno設置爲EINTR

 

(9)write函數原型

                 write(向socket文件流中寫入數據)

 

 

所需頭文件

#include <unistd.h>

函數說明

向socket文件流中寫入數據,這裏僅說明此函數應用於socket的情況

函數原型

ssize_t write (int fd,const void *buf,size_t count)

函數傳入參數

 

fd: socket文件描述符

buf:寫入數據的首地址

count:最大寫入字節數

函數返回值

成功:實際寫入的字節數

失敗:-1,錯誤代碼存放在error中

附加說明

調用函數write向socket文件流寫數據時,有如下幾種情況:

①        套接字發送緩衝區有足夠空間,返回發送的字節數

②        TCP協議接收到RST數據,返回-1,同時errno設置爲ECONNRESET

③        進程阻塞過程中接收到信號,返回-1,同時errno設置爲EINTR

2.   高級套接字函數

recv和send函數提供了和read和write差不多的功能。不過它們提供了第四個參數來控制讀寫操作。

(1) send函數原型

send(通過socket文件描述符發送數據到對方)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

通過socket文件描述符發送數據到對方

函數原型

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

函數傳入值

s

socket文件描述符

buf

發送數據的首地址

len

發送數據的長度

flags

0:此時功能同write,flags還可以設爲以下標誌的組合

MSG_OOB:發送帶外數據

MSG_DONTROUTE:告訴IP協議,目的主機在本地網絡,沒有必要查找路由表

MSG_DONTWAIT:設置爲非阻塞操作

MSG_NOSIGNAL:表示發送動作不願被SIGPIPE信號中斷

函數返回值

成功:實際發送的字節數

失敗:-1,失敗原因存於error中

 

(2) recv函數原型

recv(通過socket文件描述符從對方接收數據)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

通過socket文件描述符從對方接收數據

函數原型

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

函數傳入值

s

socket文件描述符

len

可接收數據的最大長度

flags

0:此時功能同read,flags還可以設爲以下標誌的組合

MSG_OOB:接收帶外數據

MSG_PEEK:查看數據標誌,返回的數據並不在系統中刪除,如果再次調用recv函數會返回相同的數據內容

MSG_DONTWAIT:設置爲非阻塞操作

MSG_WAITALL:強迫接收到len大小的數據後才返回,除非有錯誤或有信號產生

函數傳出值

buf

接收數據的首地址

函數返回值

成功:實際發送的字節數

失敗:-1,失敗原因存於error中

3.   套接字屬性控制函數

系統提供getsockopt、setsockopt兩函數獲取和修改套接字結構中一些屬性,通過修改這些屬性,可以調整套接字的性能,進而調整應用程序的性能。

(1) getsockopt函數原型

getsockopt(獲取套接字的屬性)

所需頭文件

#include <sys/types.h>   

#include <sys/socket.h>

函數說明

獲取套接字的屬性

函數原型

int getsockopt(int s, int level, int optname,

                      void *optval, socklen_t *optlen)

函數傳入值

s

socket文件描述符

level

SOL_SOCKET:通用套接字選項

IPPROTO_IP:IP選項

IPPROTO_TCP:TCP選項

optname

訪問的選項名,具體見表18-3

optlen

optval的長度

函數傳出值

optval

取得的屬性值

函數返回值

成功:0

失敗:-1,失敗原因存於error中

 

表18-3 套接字屬性表

level(級別)

optname(選項名

說明

數據類型

SOL_SOCKET

 

SO_BROADCAST

允許發送廣播數據

int

SO_DEBUG

允許調試

int

SO_DONTROUTE

不查找路由

int

SO_ERROR

獲得套接字錯誤

int

SO_KEEPALIVE

保持連接

int

SO_LINGER

延遲關閉連接

struct linger

SO_OOBINLINE

帶外數據放入正常數據流

int

SO_RCVBUF

接收緩衝區大小

int

SO_SNDBUF

發送緩衝區大小

int

SO_RCVLOWAT

接收緩衝區下限

int

SO_SNDLOWAT

發送緩衝區下限

int

SO_RCVTIMEO

接收超時

struct timeval

SO_SNDTIMEO

發送超時

struct timeval

SO_REUSERADDR

允許重用本地地址和端口

int

SO_TYPE

獲得套接字類型

int

SO_BSDCOMPAT

與BSD系統兼容

int

IPPROTO_IP

 

IP_HDRINCL

在數據包中包含IP首部

int

IP_OPTINOS

IP首部選項

int

IP_TOS

服務類型

int

IP_TTL

生存時間

int

IPPRO_TCP

TCP_MAXSEG

TCP最大數據段的大小

int

CP_NODELAY

不使用Nagle算法

int

 

(2)setsockopt函數原型

setsockopt(設置套接字的屬性)

所需頭文件

#include <sys/types.h>   

#include <sys/socket.h>

函數說明

設置套接字的屬性

函數原型

int setsockopt(int s, int level, int optname,

                      const void *optval, socklen_t optlen)

函數傳入值

s

socket文件描述符

level

SOL_SOCKET:通用套接字選項

IPPROTO_IP:IP選項

IPPROTO_TCP:TCP選項

optname

設置的選項名,具體見表18-3

optval

設置的屬性值

optlen

optval的長度

函數返回值

成功:0

失敗:-1,失敗原因存於error中

 

(3)getsockopt、setsockopt函數舉例

sockopt.c源代碼如下:

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

int main()

{

    int sockfd,optval,optlen = sizeof(int);

    int sndbuf = 0 ;

    int rcvbuf = 0 ;

    int flag;

    if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

    {

        perror("socket") ;

        return -1 ;

    }

    getsockopt(sockfd,SOL_SOCKET,SO_TYPE,&optval,&optlen);

    printf("optval = %d\n",optval);

    optlen = sizeof(sndbuf);

    flag = getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf,&optlen);

    printf("sndbuf=%d\n",sndbuf) ;

    printf("flag=%d\n",flag) ;

    sndbuf = 51200;   

    flag = setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf, optlen);

    sndbuf=0 ;

    flag = getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf,&optlen);

    printf("sndbuf=%d\n",sndbuf) ;

    printf("flag=%d\n",flag) ;

    close(sockfd);

    return 0 ;

}

編譯 gcc sockopt.c -o sockopt。

執行 ./sockopt, 執行結果如下:

optval = 1

sndbuf=16384

flag=0

sndbuf=102400

flag=0

4.   UDP讀寫函數

UDP套接字是無連接協議,必須使用sendto函數發送數據,必須使用recvfrom函數接收數據,發送時需指明目的地址。sendto函數與send功能基本相同,recvfrom與recv功能基本相同,只不過sendto函數和recvfrom函數參數中都帶有對方地址信息,這兩個函數是專門爲UDP協議提供的。

(1)sendto函數原型

sendto(通過socket文件描述符發送數據到對方)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

通過socket文件描述符發送數據到對方,用於UDP協議

函數原型

ssize_t sendto(int s, const void *buf, size_t len, int flags,

                      const struct sockaddr *to, socklen_t tolen)

函數傳入值

s

socket文件描述符

buf

發送數據的首地址

len

發送數據的長度

flags

0:默認方式發送數據,flags還可以設爲以下標誌的組合

MSG_OOB:發送帶外數據

MSG_DONTROUTE:告訴IP協議,目的主機在本地網絡,沒有必要查找路由表

MSG_DONTWAIT:設置爲非阻塞操作

MSG_NOSIGNAL:表示發送動作不願被SIGPIPE信號中斷

to

存放目的主機IP地址和端口信息

tolen

to的長度,可設置爲sizeof(struct sockaddr)

函數返回值

成功:實際發送的字節數

失敗:-1,失敗原因存於error中

 

(2) recvfrom函數

recv(通過socket文件描述符從對方接收數據)

所需頭文件

#include <sys/types.h>

#include <sys/socket.h>

函數說明

通過socket文件描述符從對方接收數據,用於UDP協議

函數原型

ssize_t recvfrom(int s, void *buf, size_t len, int flags,

                        struct sockaddr *from, socklen_t *fromlen)

函數傳入值

s

socket文件描述符

len

可接收數據的最大長度

flags

0:默認方式接收數據,flags還可以設爲以下標誌的組合

MSG_OOB:接收帶外數據

MSG_PEEK:查看數據標誌,返回的數據並不在系統中刪除,如果再次調用recv函數會返回相同的數據內容

MSG_DONTWAIT:設置爲非阻塞操作

MSG_WAITALL:強迫接收到len大小的數據後才返回,除非有錯誤或有信號產生

fromlen

from的長度,可設置爲sizeof(struct sockaddr)

函數傳出值

buf

接收數據的首地址

from

存放發送方的IP地址和端口

函數返回值

成功:實際發送的字節數

失敗:-1,失敗原因存於error中

 摘錄自《深入淺出Linux工具與編程》

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