前言:前面一篇文章手把手寫C++服務器(21):Linux socket網路編程入門基礎,講解了如何建立socket連接、如何轉換/使用socket地址、如何系結/監聽/發起/接受/斷開/終止/關閉連接,socket博大精深,進階會多寫幾彈,這一講主要熟悉如何TCP、UDP讀寫以及通用資料讀寫,如何操作網路地址,socket選項設定等,進一步熟悉linux網路編程,
目錄
TCP資料讀寫:recv()、send()
UDP資料讀寫:recvfrom()、sendto()
通用資料讀寫:recvmsg()、sendmsg()
地址資訊函式:getsockname()、getpeername()
socket選項
常用選項選講:
獲取服務完整資訊:getserverbyname()、getserverbyport()
參考
TCP資料讀寫:recv()、send()
TCP是流協議,recv()和send()用于讀寫緩沖區:
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recv(int sockfd,void*buf,size_t len,int flags);
ssize_t send(int sockfd,const void*buf,size_t len,int flags);
recv讀取sockfd上的資料, buf和len引數分別指定讀緩沖區的位置和大小, flags引數通常設定為0即可,
recv成功時回傳實際讀取到的資料的長度, 它可能小于我們期望的長度len, 因此我們可能要多次呼叫recv, 才能讀取到完整的資料,
send往sockfd上寫入資料, buf和len引數分別指定寫緩沖區的位置和大小, send成功時回傳實際寫入的資料的長度, 失敗則回傳-1并設定errno,
flags引數:一般設0,其他數值定義如下 MSG_OOB 傳送的資料以out-of-band 送出, MSG_DONTROUTE 取消路由表查詢 MSG_DONTWAIT 設定為不可阻斷運作 MSG_NOSIGNAL 此動作不愿被SIGPIPE 信號中斷,
UDP資料讀寫:recvfrom()、sendto()
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, int void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
recvfrom:用于讀取sockfd上面的資料;
sendto:往sockfd上寫入資料;
buf:緩沖區的位置
len:緩沖區大小
相比于tcp的兩個API recv()和send(),引數多了地址src_addr和地址的長度addrlen,這是因為UDP沒有連接的概念,每次讀取資料都需要獲取發送端的socket地址,
通用資料讀寫:recvmsg()、sendmsg()
通用的意思是TCP和UDP都能使用
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
ssize_r sendmsg(int sockfd, struct msghdr* msg, int flags);
msghdr結構的定義:
#include<sys/socket.h>
struct msghdr {
void * msg_name ; / * 訊息的協議地址 * / 協議地址和套介面資訊,在非連接的UDP中,發送者要指定對方地址埠,接受方用于的到資料來源,如果不需要的話可以設定為NULL(在TCP或者連接的UDP中,一般設定為NULL)
socklen_t msg_namelen ; / * 地址的長度 * /
struct iovec * msg_iov ; / * 多io緩沖區的地址 * /
int msg_iovlen ; / * 緩沖區的個數 * /
void * msg_control ; / * 輔助資料的地址 * /
socklen_t msg_controllen ; / * 輔助資料的長度 * /
int msg_flags ; / * 接收訊息的標識 * /
} ;
地址資訊函式:getsockname()、getpeername()
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);
int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len);
getsockname():獲取sockfd對應的本端socket地址,并將其存盤與address引數指定記憶體中,如果實際socket地址長度大于address指定記憶體中的大小,那么該socket地址將被截斷 ,
getpeername():獲取sockfd對應的遠端socket地址,用法和getsockname類似,
socket選項
讀取和設定檔案描述符的屬性和方法,
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t* restrict option_len);
int setsockopt(int sockfd, int level, int option_name, const void* option_value, socklen_t* restrict option_len);
level:指定屬性,如IPv4、IPv6、TCP等
具體選項引數含義:https://pubs.opengroup.org/onlinepubs/7908799/xns/getsockopt.html
#define SOL_IP 0
#define SOL_IPX 256
#define SOL_AX25 257
#define SOL_ATALK 258
#define SOL_NETROM 259
#define SOL_TCP 6
#define SOL_UDP 17
#define SOL_SOCKET 0xffff
常用選項選講:
1、SO_REUSEADDR
當TCP連接處于TIME_WAIT狀態的時候,SO_REUSEADDR來強制使用被處于TIME_WAIT狀態的連接占用的socket地址,使該地址能立即被重用,
2、SO_RCVBUF
TCP接識訓沖區大小
3、SO_SNDBUF
TCP發送緩沖區大小
4、SO_RCVLOWAT
TCP接識訓沖區低水位標記,被I/O復用系統呼叫用來判斷socket是否可寫,
5、SO_SNDLOWAT
TCP發送緩沖區低水位標記,被I/O復用系統呼叫用來判斷socket是否可寫,
6、SO_LINGER
控制close系統呼叫在關閉TCP連接時的行為
獲取服務完整資訊:getserverbyname()、getserverbyport()
#include <netdb.h>
struct servent* getserverbyname(const char* name, const char* proto);
struct servent* getserverbyport(int port, const char* proto);
getserverbyname:根據名稱獲取某個服務的完整資訊,
getserverbyport:根據埠號獲取某個服務的完整資訊,
兩個函式都是通過讀取/etc/services檔案來獲取服務資訊的,
引數name指定目標服務的名字;port指定埠號;proto指定服務型別,傳遞tcp表示獲取流服務,傳遞udp表示獲取資料報服務,傳遞NULL表示獲取所有型別的服務,
回傳servent結構體定義如下:
#include <netdb.h>
struct servent {
char* s_name; // 服務名稱
char** s_aliases;// 服務別名串列
int s_port; // 埠號
char* s_proto; // 服務型別
};
參考
- https://wizardforcel.gitbooks.io/linux-c-api-ref/content/282.html
- http://www.steves-internet-guide.com/tcpip-ports-sockets/
- 《linux高性能服務器編程》
- https://www.cnblogs.com/wanpengcoder/p/11749287.html
- https://blog.csdn.net/u010020404/article/details/78918937
- https://mp.weixin.qq.com/s/EyQ_RVJcDXgGkCBC-eEkQQ
- https://pubs.opengroup.org/onlinepubs/7908799/xns/getsockopt.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292947.html
標籤:其他
上一篇:IDEA 常用的小技巧匯總,JAVA 新手上路必備,快上車!(持續更新)
下一篇:Day3:資料結構之帶頭雙鏈表
