Berkeley 套接字

網際網路伯克利套接字，又稱為 BSD 套接字（Internet Berkeley sockets，BSD sockets） ，是一種應用程式介面（API），用於網路套接字（ socket）與 Unix 域套接字，包括了一個用 C 語言寫成的應用程式開發庫，主要用於實現程序間通訊，在計算機網路通訊方面被廣泛使用。

Berkeley 套接字（也作 BSD 套接字應用程式介面）剛開始是 4.2BSD Unix 作業系統（於 1983 釋出）的一套應用程式介面。然而，由於 AT&T 的專利保護著 UNIX，所以只有在 1989 年伯克利大學才能自由地釋出自己的作業系統和網路庫。

Berkeley 套接字應用程式介面形成了事實上的網路套接字的標準精髓。 大多數其他的程式語言使用與這套用 C 語言寫成的應用程式介面 類似的介面。 這套應用程式介面也被用於 Unix 域套接字（Unix domain sockets），後者可以在單機上為程序間通訊（IPC）的介面。

這種基於流的傳輸層介面（TLI）為套接字應用程式介面提供了一種選擇。 提供 TLI 應用程式介面的的系統同時也提供 Berkeley 套接字應用程式介面。}}

Berkeley 套接字介面

Berkeley 套接字介面，一個應用程式介面（API），使用一個 Internet 套接字的概念，使主機間或者一臺計算機上的程序間可以通訊。 它可以在很多不同的輸入 / 輸出裝置和驅動之上執行，儘管這有賴於作業系統的具體實現。 介面實現用於 TCP/IP 協議，因此它是維持 Internet 的基本技術之一。 它是由加利福尼亞的伯克利大學開發，最初用於 Unix 系統。 如今，所有的現代作業系統都有一些源於 Berkeley 套接字介面的實現，它已成為連線 Internet 的標準介面。

套接字介面的接入有三個不同的級別，最基礎的也是最有效的就是 raw socket 級別接入。 很少的應用程式需要在外向通訊控制的這個級別接入，所以 raw socket 級別是隻為了用於開發計算機 Internet 相關技術的。 最近幾年，大多數的作業系統已經實現了對它的全方位支援，包括 Windows XP。

使用 Berkeley 套接字的系統

由於 Berkeley 套接字是第一個 socket，大多數程式設計師很熟悉它們，所以大量系統把伯克利套接字作為其主要的網路 API。一個不完整的列表如下：

Windows Sockets (Winsock) ，和 Berkeley Sockets 很相似，最初是為了便於移植 Unix 程式。
Java Sockets
Python sockets
Perl sockets

標頭檔案

Berkeley 套接字介面的定義在幾個標頭檔案中。這些檔案的名字和內容與具體的實現之間有些許的不同。 大體上包括：

;

: 核心 BSD 套接字核心函式和資料結構。

: AFINET、AFINET6 地址集和它們相應的協議集 PFINET、PFINET6. 廣泛用於 Internet，這些包括了 IP 地址和 TCP、UDP 埠號。

;

: AFINET 和 AFINET6 地址家族和他們對應的協議家族 PFINET 和 PFINET6。在網際網路程式設計中廣泛使用，包括 IP 地址以及 TCP 和 UDP 埠號。

;

: PFUNIX/PFLOCAL 地址集。用於執行在一臺計算機上的程式間的本地通訊，不用於網路通訊。

;

: 處理數值型 IP 地址的函式。

;

: 將協議名和主機名翻譯為數值地址的函式。搜尋本地資料以及 DNS。

套接字 API 函式

這個列表是一個 Berkeley 套接字 API 庫提供的函式或者方法的概要：

socket 建立一個新的確定型別的套接字，型別用一個整型數值標識（檔案描述符），併為它分配系統資源。
bind 一般用於伺服器端，將一個套接字與一個套接字地址結構相關聯，比如，一個指定的本地埠和 IP 地址。
listen 用於伺服器端，使一個繫結的 TCP 套接字的 tcp 狀態由 CLOSE 轉至 LISTEN；作業系統核心為此監聽 socket 所對應的 tcp 伺服器建立一個 pending socket 佇列和一個 established socket 佇列；引數 backlog 指定 pending socket 佇列的長度，0 表示長度可以無限大。pending socket，就是某客戶端三次握手的 syn 包到達，核心為這個 syn 包對應的 tcp 請求生成一個 socket（狀態為 SYN_RECV），但三次握手還沒有完成時的 socket。
connect 用於客戶端，為一個套接字分配一個自由的本地埠號。 如果是 TCP 套接字的話，它會試圖獲得一個新的 TCP 連線。
accept 用於伺服器端。 它接受一個從遠端客戶端發出的建立一個新的 TCP 連線的接入請求，建立一個新的套接字，與該連線相應的套接字地址相關聯。
send 和 recv , 或者 write 和 read , 或者 recvfrom 和 sendto , 用於往 / 從遠端套接字傳送和接受資料。
close 用於系統釋放分配給一個套接字的資源。 如果是 TCP，連線會被中斷。
gethostbyname 和 gethostbyaddr 用於解析主機名和地址。
select 用於修整有如下情況的套接字列表： 準備讀，準備寫或者是有錯誤。
poll 用於檢查套接字的狀態。 套接字可以被測試，看是否可以寫入、讀取或是有錯誤。
getsockopt 用於查詢指定的套接字一個特定的套接字選項的當前值。
setsockopt 用於為指定的套接字設定一個特定的套接字選項。

更多的細節如下給出。

4.1 socket

socket 為通訊建立一個端點，為套接字返回一個檔案描述符。 socket 有三個引數：

domain 為建立的套接字指定協議集（或稱做地址族 address family)。 例如：
AF_INET 表示 IPv4 網路協議
AF_INET6 表示 IPv6
AF_UNIX 表示本地套接字（使用一個檔案）
type（socket 型別）如下：
SOCK_STREAM （可靠的面向流服務或流套接字）
SOCK_DGRAM （資料報文服務或者資料報文套接字）
SOCK_SEQPACKET （可靠的連續資料包服務）
SOCK_RAW (在網路層之上自行指定運輸層協議頭，即原始套接字)
protocol 指定實際使用的傳輸協議。 最常見的就是 IPPROTOTCP、IPPROTOSCTP、IPPROTOUDP、IPPROTODCCP。這些協議都在中有詳細說明。 如果該項為 “0” 的話，即根據選定的 domain 和 type 選擇使用預設協議。

如果發生錯誤，函式返回值為 - 1。 否則，函式會返回一個代表新分配的描述符的整數。

原型：

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

4.2 bind

bind 為一個套接字分配地址。當使用 socket 建立套接字後，只賦予其所使用的協議，並未分配地址。在接受其它主機的連線前，必須先呼叫 bind 為套接字分配一個地址。bind 有三個引數：

sockfd, 表示使用 bind 函式的套接字描述符
my_addr, 指向 sockaddr 結構（用於表示所分配地址）的指標
addrlen, 用 socklen_t 欄位指定了 sockaddr 結構的長度

如果發生錯誤，函式返回值為 - 1，否則為 0。

原型:

int bind (int sockfd, const struct sockaddr *myaddr, socklent addrlen);

4.3 listen

當 socket 和一個地址繫結之後，listen 函式會開始監聽可能的連線請求。然而，這隻能在有可靠資料流保證的時候使用，例如：資料型別 (SOCKSTREAM, SOCKSEQPACKET)。

listen 函式需要兩個引數：

sockfd, 一個 socket 的描述符.

backlog, 完成三次握手、等待 accept 的全連線的佇列的最大長度上限。對於 AFINET 型別的 socket，全連線數量為：min (backlog, somaxconn)。當佇列滿時，新的全連線會返回錯誤。somaxconn 預設為 128. 半連線佇列的最大長度可透過 sysctl 函式設定 tcpmaxsynbacklog，預設值為 256。Linux Kernel 2.2 之後，全連線佇列與半連線佇列分別叫做 accept queue 與 syns queue。根據 /proc/sys/net/ipv4/tcpabortonoverflow 裡的值為 0 表示如果三次握手第三步的時候全連線佇列滿了，那麼 server 扔掉 client 發過來的 ack，server 過一段時間再次傳送 syn+ack 給 client（也就是重新走握手的第二步），如果 client 超時等待比較短，就很容易異常；tcpabortonoverflow 為 1 表示第三次握手時如果全連線佇列滿了，server 傳送一個 reset 包給 client，表示廢掉這個握手過程和這個連線。

一旦連線被接受，返回 0 表示成功，錯誤返回 - 1。

原型:

int listen (int sockfd, int backlog);

4.4 accept

當應用程式監聽來自其他主機的面對資料流的連線時，透過事件（比如 Unix select 系統呼叫）通知它。必須用 accept 函式初始化連線。 accept 為每個連線創立新的套接字並從監聽佇列中移除這個連線。它使用如下引數：

sockfd, 監聽的套接字描述符
cliaddr, 指向 sockaddr 結構體的指標，客戶機地址資訊。
addrlen, 指向 socklen_t 的指標，確定客戶機地址結構體的大小 。

返回新的套接字描述符，出錯返回 - 1。進一步的通訊必須透過這個套接字。

Datagram 套接字不要求用 accept 處理，因為接收方可能用監聽套接字立即處理這個請求。

函式原型：

int accept (int sockfd, struct sockaddr cliaddr, socklen_t addrlen);

4.5 connect

connect 系統呼叫為一個套接字設定連線，引數有檔案描述符和主機地址。

某些型別的套接字是無連線的，大多數是 UDP 協議。對於這些套接字，連線時這樣的：預設傳送和接收資料的主機由給定的地址確定，可以使用 send 和 recv 。

返回 - 1 表示出錯，0 表示成功。

函式原型：

int connect (int sockfd, const struct sockaddr *servaddr, socklent addrlen);

4.6 select

int select (int nfds, fdset FAR readfds, fdset FAR writefds, fd_set FAR exceptfds, const struct timeval FAR timeout);

第一個引數 nfds：沒有用，僅僅為與伯克利 Socket 相容而提供。
第二個引數 readfds：指定一個 Socket 陣列，select 檢查該陣列中的所有 Socket。如果成功返回，則 readfds 中存放的是符合‘可讀性’條件的陣列成員（如緩衝區中有可讀的資料）。
第三個引數 writefds：指定一個 Socket 陣列，select 檢查該陣列中的所有 Socket。如果成功返回，則 writefds 中存放的是符合‘可寫性’條件的陣列成員（包括連線成功）。
第四個引數 exceptfds：指定一個 Socket 陣列，select 檢查該陣列中的所有 Socket。如果成功返回，則 cxceptfds 中存放的是符合‘有異常’條件的陣列成員（包括連線接失敗）。
第五個引數 timeout：指定 select 執行的最長時間，如果在 timeout 限定的時間內，readfds、writefds、exceptfds 中指定的 Socket 沒有一個符合要求，就返回 0。

4.7 getsockname 和 getpeername

int getsockname (SOCKET s, struct sockaddr name, int namelen);

getsockname 函式獲取已繫結（可能是未呼叫 bind 的系統自動繫結）的套介面本地協議地址。

int getpeername (SOCKET s, struct sockaddr name, int namelen);

getpeername 函式獲得與指定套介面連線的遠端資訊（IP:PORT）。

4.8 gethostbyname 和 gethostbyaddr

gethostbyname 和 gethostbyaddr 函式是用來解析主機名和地址的。可能會使用 DNS 服務或者本地主機上的其他解析機制（例如查詢 /etc/hosts）。返回一個指向 struct hostent 的指標，這個結構體描述一個 IP 主機。函式使用如下引數：

name 指定主機名。例如 www.wikipedia.org
addr 指向 struct in_addr 的指標，包含主機的地址。
len 給出 addr 的長度，以位元組為單位。
type 指定地址族型別 （比如 AF_INET）。

出錯返回 NULL 指標，可以透過檢查 h_errno 來確定是臨時錯誤還是未知主機。正確則返回一個有效的 struct hostent *。

這些函式並不是伯克利套接字嚴格的組成部分。這些函式可能是過時了，只能處理 IPv4 地址。在 IPv6 中，替代的新函式是 getaddrinfo and getnameinfo , 這些新函式是基於 addrinfo 資料結構。參考。

函式原型：

struct hostent gethostbyname (const char name);

struct hostent gethostbyaddr (const void addr, int len, int type);

4.9 setsockopt

int setsockopt (int sockfd, int level, int optname, void optval, socklen_t optlen);

setsockopt 函式用來設定套接字選項。

引數：

sockfd: 套接字
level: 協議層 SOLSOCKET/IPPROTOIP/IPPRO_TCP
optname: 選項名 每一個協議層都有其固定的選項名
optval: 緩衝區 set 是指向將要存放的地址，get 是指向目前存放資訊的地址
optlen: 緩衝區大小長度

在 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

4.10 ioctlsocket

int ioctlsocket (In SOCKET s, In long cmd, Inout u_long *argp);

根據第二個引數的取值，設定 socket I/O 模式：

FIONBIO：允許設定 socket 為阻塞或非阻塞：當第三個引數 argp 為 0 是阻塞模式，為非 0 則為非阻塞模式。如果已對一個套介面進行了 WSAAsynSelect 操作，則任何用 ioctlsocket 來把套介面重新設定成阻塞模式的試圖將以 WSAEINVAL 失敗。為了把套介面重新設定成阻塞模式，應用程式必須首先用 WSAAsynSelect 呼叫（IEvent 引數置為 0）來禁至 WSAAsynSelect , 或者透過設定 lNetworkEvents 引數為 0 來呼叫 WSAEventSelect。
FIONREAD：返回套接字 s 下一次自動讀入的資料量的大小。用來確定（determin）懸掛（pending）在網路輸入緩衝區中，能從 socket s 中讀取的資料總數。返回單次 recv 函式能讀取的資料的總數
SIOCATMARK：返回所有的 “緊急”（帶外）資料是否都已被讀入。僅適用於 SOCKSTREAM 型別的套介面，且該套介面已被設定為可以線上接收帶外資料（SOOOBINLINE）

4.11 inetpton 與 inetntop

inetpton 與 inetntop 兩個函式，在 ASCII 字元描述的 IP 地址與網路位元組序的 4 位元組 IP 地址之間轉換。 字母 "n" 與 "p"，分別是 numerical 與 presentation 的縮寫。

協議和地址

套接字 API 是 Unix 網路的通用介面，允許使用各種網路協議和地址。

下面列出了一些例子，在現在的 Linux 和 BSD 中一般都已經實現了。

PFLOCAL, PFUNIX, PF_FILE

Local to host (pipes and file-domain)

PF_INET IP protocol family

PF_AX25 Amateur Radio AX.25

PF_IPX Novell Internet Protocol

PF_APPLETALK Appletalk DDP

PF_NETROM Amateur radio NetROM

PF_BRIDGE Multiprotocol bridge

PF_ATMPVC ATM PVCs

PF_X25 Reserved for X.25 project

PF_INET6 IP version 6

PF_ROSE Amateur Radio X.25 PLP

PF_DECnet Reserved for DECnet project

PF_NETBEUI Reserved for 802.2LLC project

PF_SECURITY Security callback pseudo AF

PFKEY PFKEY key management API

PFNETLINK, PFROUTE

routing API

PF_PACKET Packet family

PF_ASH Ash

PF_ECONET Acorn Econet

PF_ATMSVC ATM SVCs

PF_SNA Linux SNA Project

PF_IRDA IRDA sockets

PF_PPPOX PPPoX sockets

PF_WANPIPE Wanpipe API sockets

PF_BLUETOOTH Bluetooth sockets

socket 的通用 address 描述結構 sockaddr 是一個 16 位元組大小的結構（2+14），safamily 可以認為是 socket address family 的縮寫。另外的 14 位元組是用來描述地址。當指定 safamily=AFINET 之後，sadata 的形式也就被固定了下來：最前端的 2 位元組用於記錄 16 位的埠，緊接著的 4 位元組用於記錄 32 位的 IP 地址，最後的 8 位元組清空為零。

struct sockaddr

{

unsigned short sa_family;

char sa_data14;

};

struct sockaddr_in //means socket address internet

{unsigned short sin_family; //sin means socket (address) internet

unsigned short sin_port;

struct inaddr sinaddr;

char sin_zero8;

};

struct in_addr

{unsigned long s_addr; //means source address};

使用 TCP 的伺服器客戶機舉例

6.1 伺服器

設定一個簡單的 TCP 伺服器涉及下列步驟：

呼叫 socket 函式建立套接字，應當使用的引數參見例程。
呼叫 bind 函式把套接字繫結到一個監聽埠上。注意 bind 函式需要接受一個 sockaddrin 結構體作為引數，因此在呼叫 bind 函式之前，程式要先宣告一個 sockaddrin 結構體，用 memset 函式將其清零，然後將其中的 sinfamily 設定為 AFINET，接下來，程式需要設定其 sinport 成員變數，即監聽埠。需要說明的是，sinport 中的埠號需要以網路位元組序儲存，因此需要呼叫 htons 函式對埠號進行轉換（函式名是 "host to network short" 的縮寫）。
呼叫 listen 函式，使該套接字成為一個處在監聽狀態的套接字。
接下來，伺服器可以透過 accept 函式接受客戶端的連線請求。若沒有收到連線請求，accept 函式將不會返回並阻塞程式的執行。接收到連線請求後，accept 函式會為該連線返回一個套接字描述符。accept 函式可以被多次呼叫來接受不同客戶端的連線請求，而且之前的連線仍處於監聽狀態 —— 直到其被關閉為止。
現在，伺服器可以透過對 send，recv 或者對 write，read 等函式的呼叫來同客戶端進行通訊。
對於一個不再需要的套接字，可以使用 close 函式關閉它。 Note that if there were any calls to fork , each process must close the sockets it knew about (the kernel keeps track of how many processes have a descriptor open), and two processes should not use the same socket at once.

/ Server code in C /

include

int main (void)

{

struct sockaddr_in stSockAddr;

int SocketFD = socket (PFINET, SOCKSTREAM, IPPROTO_TCP);

if (-1 == SocketFD)

{perror ("can not create socket");

exit (EXIT_FAILURE);

}

memset (&stSockAddr, 0, sizeof (struct sockaddr_in));

stSockAddr.sinfamily = AFINET;

stSockAddr.sin_port = htons (1100);

stSockAddr.sinaddr.saddr = INADDR_ANY;

if (-1 == bind (SocketFD,(const struct sockaddr *)&stSockAddr, sizeof (struct sockaddr_in)))

{perror ("error bind failed");

close (SocketFD);

exit (EXIT_FAILURE);

}

if (-1 == listen (SocketFD, 10))

{perror ("error listen failed");

close (SocketFD);

exit (EXIT_FAILURE);

}

for (;;)

{int ConnectFD = accept (SocketFD, NULL, NULL);

if (0> ConnectFD)

{perror ("error accept failed");

close (SocketFD);

exit (EXIT_FAILURE);

}

/ perform read write operations ... /

shutdown (ConnectFD, SHUT_RDWR);

close (ConnectFD);

}

close (SocketFD);

return 0;

}

Python 實現：

from socket import from time import ctime

HOST=

PORT=1100

BUFSIZ=1024

ADDR=(HOST, PORT)

sock=socket (AFINET, SOCKSTREAM)

sock.bind (ADDR)

sock.listen (5)

while True:

print ('waiting for connection')

tcpClientSock, addr=sock.accept

print ('connect from ', addr)

while True:

try:

data=tcpClientSock.recv (BUFSIZ)

except:

print (e)

tcpClientSock.close

break

if not data:

break

s='Hi,you send me :% s % s' %(ctime , data.decode ('utf8'))

tcpClientSock.send (s.encode ('utf8'))

print (ctime , ':', data.decode ('utf8'))

tcpClientSock.close

sock.close

6.2 客戶機

建立一個客戶機連線涉及以下步驟：

呼叫 socket 建立套接字。
用 connect 連線到伺服器，類似伺服器端的操作，將一個 sinfamily 設為 AFINET,sinport 設為伺服器的監聽埠（依然要以網路位元組序）,sinaddr 設為伺服器 IP 地址的（還是要用網路位元組序）的 sockaddr_in 作為引數傳入。
用 send 和 recv 或者 write 和 read 進行通訊。
用 close 終止連線。如果呼叫 fork , 每個程序都要用 close 。

/ Client code in C /

include

int main (void)

{

struct sockaddr_in stSockAddr;

int Res;

int SocketFD = socket (PFINET, SOCKSTREAM, IPPROTO_TCP);

if (-1 == SocketFD)

{perror ("cannot create socket");

exit (EXIT_FAILURE);

}

memset (&stSockAddr, 0, sizeof (struct sockaddr_in));

stSockAddr.sinfamily = AFINET;

stSockAddr.sin_port = htons (1100);

Res = inetpton (AFINET, "192.168.1.3", &stSockAddr.sin_addr);

if (0> Res)

{perror ("error: first parameter is not a valid address family");

close (SocketFD);

exit (EXIT_FAILURE);

}

else if (0 == Res)

{perror ("char string (second parameter does not contain valid ipaddress");

close (SocketFD);

exit (EXIT_FAILURE);

}

if (-1 == connect (SocketFD, (const struct sockaddr *)&stSockAddr, sizeof (struct sockaddr_in)))

{perror ("connect failed");

close (SocketFD);

exit (EXIT_FAILURE);

}

/ perform read write operations ... /

shutdown (SocketFD, SHUT_RDWR);

close (SocketFD);

return 0;

}

Python 實現：

from socket import

HOST='192.168.1.3'

PORT=1100

BUFSIZ=1024

ADDR=(HOST, PORT)

client=socket (AFINET, SOCKSTREAM)

client.connect (ADDR)

while True:

data=input ('>')

if not data:

break

client.send (data.encode ('utf8'))

data=client.recv (self.BUFSIZ)

if not data:

break

print (data.decode ('utf8'))

使用 UDP 的伺服器客戶機舉例

使用者資料報協議（UDP）是一個不保證正確傳輸的無連線協議。 UDP 資料包可能會亂序到達，多次到達或者直接丟失。但是設計的負載比 TCP 小。

UDP 地址空間，也即是 UDP 埠，和 TCP 埠是沒有關係的。

7.1 伺服器

Code may set up a UDP server on port 7654 as follows:

include
include / for close for socket /
include

int main (void)

{int sock = socket (PFINET, SOCKDGRAM, IPPROTO_UDP);

struct sockaddr_in sa;

char buffer1024;

ssize_t recsize;

socklen_t fromlen;

memset (&sa, 0, sizeof (sa));

sa.sinfamily = AFINET;

sa.sinaddr.saddr = INADDR_ANY;

sa.sin_port = htons (7654);

if (-1 == bind (sock,(struct sockaddr *)&sa, sizeof (struct sockaddr)))

{perror ("error bind failed");

close (sock);

exit (EXIT_FAILURE);

}

for (;;)

{printf ("recv test....\n");

recsize = recvfrom (sock, (void ) buffer, 1024, 0, (struct sockaddr )&sa, &fromlen);

if (recsize

上面的無限迴圈用 recvfrom 接收給 UDP 埠 7654 的資料包。使用如下引數：

指向快取資料指標
快取大小
標誌
地址
地址結構體大小

同樣功能的 Python 實現：

import socket

port=7654

s=socket.socket (socket.AFINET,socket.SOCKDGRAM)

從指定的埠，從任何傳送者，接收 UDP 資料

s.bind ((,port))

print (' 正在等待接入...')

while True:

接收一個數據

data,addr=s.recvfrom (1024)

print ('Received:',data,'from',addr)

7.2 客戶機

用 UDP 資料包傳送一個 "Hello World!" 給地址 127.0.0.1（迴環地址），埠 7654 。

include
include / for close for socket /

int main (int argc, char *argv)

{

int sock;

struct sockaddr_in sa;

int bytessent, bufferlength;

char buffer200;

buffer_length = snprintf (buffer, sizeof (buffer), "Hello World!");

sock = socket (PFINET, SOCKDGRAM, IPPROTO_UDP);

if (-1 == sock) / if socket failed to initialize, exit /

{printf ("Error Creating Socket");

exit (EXIT_FAILURE);

}

memset (&sa, 0, sizeof (sa));

sa.sinfamily = AFINET;

sa.sinaddr.saddr = htonl (0x7F000001);

sa.sin_port = htons (7654);

bytessent = sendto (sock, buffer, bufferlength, 0,(struct sockaddr*)&sa, sizeof (struct sockaddr_in));

if (bytes_sent

buffer 指定要傳送資料的指標，buffer_length 指定快取內容的大小。

同樣功能的 Python 實現：

import socket

port=7654

host='localhost'

s=socket.socket (socket.AFINET,socket.SOCKDGRAM)

s.sendto (b'Hello World!',(host,port))