介紹套接字
套接字是網際網路使用者層的介面,可以實現不同終端間的資料傳遞;在c中套接字的各種函式和資料結構分布在很多庫里,在此不詳細說每乙個函式在哪個庫中,使用到的程式中使用到套接字的函式都包括在以下庫中
#include
#include
#include
#include
#include
執行環境
執行環境為windows子系統ubuntu 18.04 lts
程式作用
程式分為兩個部分:客戶端程式和伺服器程式
客戶端程式把字串yyyyyyyyyy傳送給伺服器,然後接受伺服器傳送的時間並顯示
伺服器程式接受客戶端傳送的資料.顯示客戶端的ip位址,埠號,客戶端傳來的字串.最終把系統時間傳回客戶端.
客戶端程式
下面分塊介紹客戶端程式
首先宣告巢狀字,實際上巢狀字就是乙個int型資料,使用socket函式初始化即可.下面socket函式傳遞的第乙個引數為ipv4協議(pf_inet);第二個引數為無連線通訊(sock_dgram);第三個引數為udp協議(ipproto_udp)
// 建立套接字,引數:ipv4協議,連線型別,udp協議
int client_fd =
socket
(pf_inet, sock_dgram, ipproto_udp)
;
struct sockaddr_in
;
伺服器位址只是用了三個元素,協議簇初始為af_inet,表示ipv4;sin_addr.s_addr這個元素可以看到是ip位址,但是在這裡要把用字串表示的ip位址通過inet_addr()轉成需要的格式;最後乙個埠號賦值為12000
注:這個結構體是繼承struct sockaddr的結構體,兩者大小一樣,一般要使用的時候需要將struct sockaddr_in *轉成struct sockaddr *
// 伺服器的位址
struct sockaddr_in server_addr;
int addr_size =
sizeof
(struct sockaddr)
;// 清空伺服器位址
memset
(&server_addr,
0, addr_size)
;// 位址為ip位址
server_addr.sin_family = af_inet;
//伺服器ip位址,127.0.0.1是本機,也就是傳給自己電腦
server_addr.sin_addr.s_addr=
inet_addr
("127.0.0.1");
//伺服器端口號,這個可以隨意1024-65535
server_addr.sin_port=
htons
(12000
);
接下來開始對伺服器傳送字串buf;這裡用到函式sendto();第乙個引數是客戶端的套接字client_fd;第二個引數是要傳送的字串buf;第三個引數是緩衝區大小,即字串的最大長度;第四個引數不用管,傳0;第五個引數傳遞伺服器的位址,但是這裡要轉成基類的指標;第六個引數傳遞位址結構的大小,這個在之前已經計算得出為addr_size,這裡也可寫為sizeof(struct sockaddr)
// 初始化要傳送的字串
memset
(buf,
'y',10)
;printf
("sending: '%s'\n"
,buf)
;// 傳送資料,引數如下
// 客戶套接字,字串,字串最大長度,0,伺服器位址,位址大小
sendto
(client_fd, buf, maxbuf,0,
(struct sockaddr *
)&server_addr, addr_size)
;
最後要接受從伺服器傳來的資訊,這裡使用recvfrom()函式,revcfrom函式和sendto差不多,要注意的是它的返回值.當成功接收時返回值為讀取到字串的長度,在程式中儲存cc裡面,之後的程式用到cc給字串加上結束符』\0』.具體程式如下:
int cc =
recvfrom
(client_fd, buf, maxbuf,0,
(struct sockaddr *
)&server_addr,
&addr_size)
; buf[cc]
='\0'
;printf
("%s"
, buf)
;
整個客戶端完整**:
#include
#include
#include
#include
#include
#include
#define maxbuf 20000
intmain()
伺服器程式
伺服器程式和客戶端很像,只需要討論其中的一些差別即可
伺服器端程式要建立套接字並繫結到伺服器的位址上,繫結的函式使用bind函式;這個函式的第乙個引數就是伺服器的套接字;第二個引數是伺服器的位址**成基類);第三個引數是位址大大小
// 建立套接字並繫結
int server_sock =
socket
(af_inet, sock_dgram, ipproto_udp)
;// 清空伺服器位址
memset
(&server_addr,
0, addr_size)
;// 位址為ip位址
server_addr.sin_family = af_inet;
// inaddr_any表示可以接受任意的ip位址發來的訊息
server_addr.sin_addr.s_addr = inaddr_any;
// 埠
server_addr.sin_port =
htons
(12000);
// 繫結套接字,和位址
bind
(server_sock,
(struct sockaddr *
)&server_addr,
sizeof
(struct sockaddr)
);
伺服器程式還要接受多個客戶程式的請求,因此在這裡設定了乙個死迴圈,每次伺服器程式接受客戶資訊並且傳送時間之後,都等待另乙個客戶的資訊,程式最終需要在命令列中輸入ctrl+c結束,迴圈的過程如下:
printf
("the server is ready\n-----------------------\n");
while(1
)
總客戶程式**如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define maxbuf 20000
intmain
(int argc,
char
**ar**)
return0;
}
執行結果
先啟動伺服器程式,可以看到如下介面
接下來啟動客戶端程式,有如下介面;在這裡可以看到客戶程式從伺服器程式返回的資料中獲得了時間
再次檢視伺服器端結果如下:
可以看到伺服器程式已經取出ip位址,埠號和客戶傳來的字串
感覺c語言編寫套接字真的很多細節要注意,只是很粗略講一下都是好幾千字,下次將tcp套接字估計更長,可能考慮以後寫一些python的**這樣看起來比較方便
UDP套接字程式設計
與面向連線的協議相比,面向無連線協議極為不同。其中乙個重要的不同點就是客戶端與伺服器之間不必建立連線。對於udp套接字程式設計而言,伺服器建立套接字後,呼叫bind 函式將套接字與準備接收資料的介面繫結在一起。和tcp程式設計不同的是,應用程式不必呼叫listen 和accept 函式等待客戶端的連...
UDP套接字程式設計
udp是使用者資料報協議,與tcp協議一樣,在網路中處理資料報,是一種無連線的傳輸層協議,具有不可靠性,udp有不提供資料報分組 組裝和不能對資料報進行排序的缺點,也就是說,當報文傳送之後,是無法得知其是否安全完整到達的。基於udp的客戶端伺服器 伺服器 include include includ...
關於udp套接字
setsockopt so reuseaddr 同一終端先後兩次執行udp server,該選項無影響。兩個 或多個 終端同時執行udp server,配置該選項時,僅第乙個終端執行成功 不配置時,所有終端均可成功執行udp server。udp客戶端呼叫connect 實現 不發起三次握手 僅將服...