套接字設置
利用套接字能完成很多豐富得應用,但要想利用套接字實現更復雜得應用,必定會涉及到調整套接字屬性,通過調整套接字屬性,能夠實現廣播、組播、地址重用、數據緩衝區以及數據超時處理等功能。
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
參數sockfd----用於指定要操作的套接字
level ----- 用於指定套接字的操作層次,及當前要操作得協議層次
SOL_SOCKET :通用套接字層,用於設置通用套接字
IPPROTO_IP :IP協議層,用於設置IP層
IPPROTO_TCP:TCP協議層,用於設置TCP層
參數optname\optval\optlen是3個相關得參數,optname對應選項名稱,及針對那個選項設置,optval是選項所採用得數據結構,optlen是數據結構所佔的字節數。以上3個參數的配置取決於level參數得設置。
選項名稱 說明 數據類型
========================================================================
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_REUSEADDR允許重用本地地址和端口int
SO_TYPE 獲得套接字類型 int
SO_BSDCOMPAT 與BSD系統兼容 int
========================================================================
IPPROTO_IP
------------------------------------------------------------------------
IP_HDRINCL 在數據包中包含IP首部 int
IP_OPTINOSIP首部選項 int
IP_TOS服務類型
IP_TTL 生存時間 int
IP_ADD_MEMBERSHIP 組播 sizeof(ip_mreq)
========================================================================
IPPRO_TCP
------------------------------------------------------------------------
TCP_MAXSEGTCP最大數據段的大小 int
TCP_NODELAY 不使用Nagle算法 int
========================================================================
套接字設置應用:
1、數據收發時限設置
這項功能是設置數據包得接收與發送時限,以提升應用程序性能,即在規定的時間內,如果沒有數據到來或數據包沒有發送成功,則轉入相應模塊進行處理。
Struct timeval timeout;
timeout . tv_sec = 5;
timeout . tv_usec = 0;
//接收時限
setsockopt( serversocket , SOL_SOCKET, SO_RECVTIMEO,(char *)&timeout, sizeof(timeoout));
//發送時限
setsockopt( serversocket , SOL_SOCKET, SO_SNDTIMEO,(char *)&timeout, sizeof(timeoout));
2、修改數據收發緩存區
在接收與發送數據時,由於實際數據可能遠遠大於默認緩存區得大小,要想解決這個問題,除了可以循環調用接收與發送函數以外,還可以通過設置SO_RCVBUF或SO_SNDBUF屬性得方式完成。
//接收緩衝區
int opt = 1024 * 1024;
setsockopt( serversocket, SOL_SOCKET, SO_RCVBUF,(const char *) &opt, sizeof(opt));
//發送緩衝區
setsockopt( serversocket, SOL_SOCKET, SO_SNDBUF,(const char *) &opt, sizeof(opt));
3、廣播設置
在發送數據包的時候,若希望該Socket發送得數據具有廣播特性,則要進行下列得設置:
int bBroadcast = 1;
setsockopt(serversocket, SOL_SOCKET, SO_BROADCAST, (const char *) &bBroadcast, sizeof(bBroadcast));
4、直接數據複製
爲提升系統性能,在發送或接收數據時,可以主動設置數據不經歷由系統緩存區到套接字緩存區的拷貝,這個功能是由設置SO_SNDBUF或SO_RECVBUF的參數值爲0來實現的。
Int opt = 0;
//設置發送
setsockopt( serversocket, SOL_SOCKET, SO_SNDBUF,(const char*) &opt, sizeof(opt));
//設置接收
setsockopt( serversocket, SOL_SOCKET, SO_RECVBUF,(const char*) &opt, sizeof(opt));
組播技術
在internet的某些應用中,有時候需要大量用戶相互協作,若協作規模比較小,可以採用單播通信方式,直接點對點,單點對點得缺點是不管是信息的發送方還是接收方,都需要維護一個用戶列表,代價比較高,有時候也可以採用廣播通信方式,但如果是在擁有數十萬個節點得網絡中,使用廣播會很低效,甚至不可能,因爲此時大多數得主機對此信息可能不感興趣。
因此需要一種折中得辦法,既能實現小組範圍內得互聯,又能高校運轉,爲此,組播就應運而生。
224.0.0.1
編程流程:
1、套接字基本屬性
IP_ADD_MEMBERSHIP
若要加入一個組播組,則要在setsockopt()中設置該選項,其中有一個重要的結構體:
struct ip_mreq
{
struct in_addr imr_multiaddr; //指定組播組的地址
struct in_addr imr_interface; // 指定接口得IPV4地址
};
IP_DROP_MEMBERSHIP
用來從某個組播組中退出
IP_MULTICAST_IF
該選項可以修改網絡接口,在結構體ip_mreq中定義新的接口
IP_MULTICAST_TTL
該選項用於設置組播報文的數據包的TTL(生存時間),默認值是1,表示數據包只能在本地的子網中傳送。
IP_MULTICAST_LOOP
該選項表示組播組中的成員自已也會收到它向本組發送的報文。
2、組播工作流程
服務器:
struct sockaddr_in address;
memset(&address, 0 , sizeof(address));
address . sin_family = AF_INET;
address . sin_port = htons(8888);
address . sin_addr . s_addr = inet_addr(“224.0.0.1”);
客戶端:
//在同一個主機上進行組播設置套接口
bind(sockCli,(struct sockaddr*)&addrSer,sizeof(addrSer));
struct ip_mreq multiaddress;
multiaddress . imr_multiaddr.s_addr = inet_addr(“224.0.0.1”); in_addr
multiaddress . imr_interface . s_addr = htonl(INADDR_ANY);
//加入組播組
if ( setsockopt ( client_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multiaddress , sizeof (multiaddress)) < 0)
{
printf(.......)
return 0;
}
//結束時退出組播組
if ( setsockopt ( client_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, &multiaddress , sizeof (multiaddress)) < 0)
{
printf(.......)
return 0;
}
socket(AF_INET,SOKC_STREAM\SOCK_DGRAM\SOCK_RAW)
原始套接字
原始套接字是一種套接字底層技術,它工作在網絡層,利用原始套接字可以完成以下功能:
1、設置網卡爲混雜模式,嗅探當前網絡流經本網卡得所有數據包
2、構造各種數據包(IP,ICMP,TCP,UDP),並進行發送
3、進行新協議得驗證
原始套接字的創建:
//創建可以獲得所有IP層得數據報文的套接字
int rawsock = socket(AF_INET, SOCK_RAW, htons(ETH_P_IP));
協議碼 協議名
IPPROTO_ICMP ICMP 協議
ETH_P_IP IP 協議
IPPROTO_TCP TCP 協議
IPPROTO_UDP UDP 協議