設定和獲得套介面選項
獲得套介面選項
int getsockopt ( int sockfd, int level, int optname, void * optval, socklen_t *opteln )
設定套介面選項:
int setsockopt ( int sockfd, int level, int optname, const void * optval, socklen_t *opteln )
引數含意
sockfd(套接字): 指向乙個開啟的套介面描述字
level:(級別): 指定選項**的型別。
sol_socket: 基本套介面
ipproto_ip: ipv4套介面
ipproto_ipv6: ipv6套介面
ipproto_tcp: tcp套介面
optname(選項名): 選項名稱
optval(選項值): 是乙個指向變數的指標 型別:整形,套介面結構, 其他結構型別:linger{}, timeval
optlen(選項長度) :optval 的大小
返回值:標誌開啟或關閉某個特徵的二進位制選項
用於設定socket細節
so_reuseaddr 重用位址
當開啟某一埠的程式非正常退出,可能埠仍被占用,第二次執行程式就會報」addr in use」無法使用這一埠
用so_reuseaddr 可以防止這一問題.伺服器的socket,最好用這一選項.
n = socket(af_inet, sock_stream, ipproto_tcp);
val = 1;
setsockopt(n, sol_socket, so_reuseaddr, (char *) &val, sizeof (val));
// some code ...
if ((bind(n, (struct sockaddr *) &sin, sizeof (sin)) < 0)
|| (listen(n, qlen) < 0))
exit(1);
so_broadcast udp廣播選項
一般在傳送udp資料報的時候,希望該socket傳送的資料具有廣播特性
用sendto傳送時,廣播位址可以寫
from.sin_addr.s_addr=inaddr_broadcast;
或是根據ip位址和掩碼算出的子網的廣播位址
int bbroadcast=1; setsockopt(s,sol_socket,so_broadcast,(const char*)&bbroadcast,sizeof(int));
udp廣播例項
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
else
printf("create socket./n/r");
/* 設定通訊方式對廣播,即本程式傳送的乙個訊息,網路上所有主機均可以收到 */
yes = 1;
setsockopt(sock, sol_socket, so_broadcast, &yes, sizeof(yes));
/* 唯一變化就是這一點了 */
/* 設定對方位址和埠資訊 */
s_addr.sin_family = af_inet;
if (argv[2])
s_addr.sin_port = htons(atoi(argv[2]));
else
s_addr.sin_port = htons(7838);
//windows
if (argv[1])
s_addr.sin_addr.s_addr = inet_addr(argv[1]);
else
/* 傳送udp訊息 */
addr_len = sizeof(s_addr);
strcpy(buff, "hello i'm here");
len = sendto(sock, buff, strlen(buff), 0,
(struct sockaddr *) &s_addr, addr_len);
if (len < 0)
printf("send success./n/r");
return 0;
}客戶端首先收下定長的結構體,從中讀取檔名和檔案長度.然後連續接收檔案長度的字元,即可將檔案完整接收下來.
由於tcp是不會丟失資料,因此只有二種可能,一種是接收失敗,一種是把檔案完整接收下來.
檔案的阻塞函式
一般檔案讀取函式read,socket的接收函式recv,recvfrom都是阻塞型函式,即沒有資料收到時,整個程式被阻塞這個函式
在伺服器軟體上,經常要接收多個客戶端的資料.如果單純採用recv造成整個程式的阻塞.
一種方法採用多執行緒.
更為常用是採用多路復用函式select來同時控制多個socket/file 描述符.
select多路復用
select系統呼叫是用來讓我們的程式監視多個檔案控制代碼(file descrīptor)的狀態變化的。程式會停在select這裡等待,直到被監視的檔案控制代碼有某乙個或多個發生了狀態改變。
普通檔案讀寫
socket的收發
裝置檔案的收發
fd_set資料結構
select主要操作fd_set的資料結構.fd_set是乙個檔案描述符的向量陣列
大體上可以把fd_set看成乙個只有32項的整數陣列.
每乙個socket或fd都是fd_set中的一項,
一般採用一組巨集來操作fd_set
void fd_set(int fd,fd_set *fdset)
void fd_clr(int fd,fd_set *fdset)
fd_clr將fd從fdset裡面清除
void fd_zero(fd_set *fdset)
fd_zero從fdset中清除所有的檔案描述符
int fd_isset(int fd,fd_set *fdset)
fd_isset判斷fd是否在fdset集合中
typedef struct fd_set
select定義
int select(int max_fd, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
其中max_fd為我們要監聽的套接字中值最大的乙個,同時在呼叫select是要將其加1,
readfd即為我們監聽的要進行讀操作的套接字連線集合,
第三個引數是我們監聽的要進行寫操作的套接字連線集合,
第四個引數用於異常,而最後乙個引數可以用來設定超時,這裡同樣使用了struct timeval結構,
當有檔案被寫時,返回乙個大於0值,出錯返回乙個負數,等於表示在timeout的時間,沒有任何讀寫,select是超時返回的
select()的使用
select同時監控多個啟用的socket(最大值一般為1024)
當相應的socket上有資料接收時,select將其值寫入readfd值中.並返回乙個大於0值.
這樣通過fd_isset可以查出是哪乙個socket被讀寫.因為只有乙個阻塞點.大大提高程式的效能
因為帶有超時機制,也能防止長時間阻塞導致程式無法響應的後果
select也能處理一般的檔案或裝置檔案,如把標準輸入或普通檔案加入到監控的集合中
select例項
int main() else if(ret == 0)
else
} select的socket下使用流程
select 的使用是固定的流程
socket(...); bind(...); listen(...); while(1) else
}
練習多個檔名可由配置檔案或直接寫在原始碼裡,請將廣播和聊天伺服器**移植到linux上
windows 下的網路程式設計
用簡單的 和演示說明了winsocket的使用一般必要步驟。先看看程式執行的效果吧 最上面的乙個視窗為服務端,下面的視窗為客戶端,服務端的主迴圈負責接收資料。如果客戶端輸出 exit 字串的話,則服務端和客戶端程式終止。這個示例主要是通過簡單的 讓初學者了解到wsa winsocketapi 的啟動...
windows下的網路程式設計
windows下的網路程式設計 做過windows網路程式設計的人都知道,微軟的mfc把複雜的winsock api函式封裝到類裡,這使得編寫網路應用程式更容易。即windows既提供上層的網路api函式也提供底層的api函式。1 對於採用上層的api函式而言 若採用csocket類定義乙個物件ob...
VS下C 網路程式設計
提供了強制資料立即傳送的操作指令 push,tcp軟體收到該操作指令後,就立即將本段資料傳送出去,而不必等待傳送緩衝區滿 include pragma comment lib,ws2 32.lib int tmain int argc,tchar argv socket socket socksrv...