windows網路程式設計 select模型

2021-09-20 21:07:03 字數 3842 閱讀 4956

select模型與一般模型的區別是selete模型使用fd_set資料型別和select函式在核心裡維護一張存有連線上的socket表,使用select輪循處理這些socket,實現同時與多個socket連線。

基本工作原理:建立socket,繫結,監聽,開個死迴圈,當發現有socket請求連線後把該socket寫入全域性變數的fd_set資料型別中,給另乙個執行緒處理,總監聽數-1,處理執行緒會接受fd_set全域性變數,(開死迴圈)使用select函式堵塞監聽表中的socket(輪循該錶(fd-set)),當發現有表中的某個或多個socket有資訊傳過來時,再輪循一次該錶,逐個處理傳過來的資訊。如果某個socket斷開連線(recv傳送訊息過來,返回值是0),則把該socket從表中移除。總監聽數量+1.

使用的函式:

int select(

int nfds,//忽略,只是為了保持與早期的berkeley套接字應用程式的相容

fd_set far* readfds,//可讀性檢查(有資料可讀入,連線關閉,重設,終止),為空則不檢查可讀性

fd_set far* writefds,//可寫性檢查(有資料可發出),為空則不檢查可寫性

fd+set far* exceptfds,//帶外資料檢查(帶外資料),為空則不檢查

const struct timeval far* timeout//超時

);

struct timeval

;

void fd_set(int fd, fd_set *set);   //在set中設定檔案描述符fd

void fd_clr(int fd, fd_set *set); //清除set中的fd位

int fd_isset(int fd, fd_set *set); //判斷set中是否設定了檔案描述符fd

void fd_zero(fd_set *set); //清空set中的所有位(在使用檔案描述符集前,應該先清空一下)

//(注意fd_clr和fd_zero的區別,乙個是清除某一位,乙個是清除所有位)

例項:

伺服器:

#include #include //必須放在windows.h前面

#include #include #pragma comment(lib, "ws2_32.lib")

fd_set g_fdclientsock; //可以理解為一張存了需要等待的socket的陣列。

int clientnum = 0;

dword winapi listenthreadproc(lparam lparam)

memset(recvbuffer, 0, 1024);

while (1)

else//如果接收失敗,則從集合中清除響應socket,並把客戶端數量減1??為什麼要這個操作,不刪除,fd表的負擔太大了麼?}}

} }if (recvbuffer)

return 0;

}int main()

//建立用於監聽的套接字 af_inet:ipv4版本

socket socksrv = socket(af_inet, sock_stream, 0);

if (socksrv == invalid_socket)

//位址繫結-告訴作業系統是在哪乙個位址及埠

sockaddr_in addrsrv;

addrsrv.sin_family = af_inet;

addrsrv.sin_port = htons(port); //1024以上的埠號,htons本地轉換為網路資料

addrsrv.sin_addr.s_un.s_addr = htonl(inaddr_any);//電腦上所有的網路ip

int retval = bind(socksrv, (lpsockaddr)&addrsrv, sizeof(sockaddr_in));

if (retval == socket_error)

if (listen(socksrv, 5/*somaxconn*/) == socket_error)

sockaddr_in addrclient;//用於獲取連線上來的人的位址資訊

int len = sizeof(sockaddr);

//建立執行緒

createthread(null, null, (lpthread_start_routine)listenthreadproc, null, null, null);

//繫結好之後就在這裡監聽,每次監聽到sockket就把他寫入核心的fd_set(g_fdclientsock是全域性,另乙個執行緒能看到),之後的就交給另乙個執行緒,總共就需要2個執行緒

while (clientnum < fd_setsize)

else

fd_set(clientsock, &g_fdclientsock);//新增到集合中去

clientnum++;//每次接收到乙個人就+1,目前最多接收64個客戶,可以改到最大值的1024

} closesocket(socksrv);

wsacleanup();

system("pause");

return 0;

}

客戶端:(客戶端和一般模型的客戶端一樣)

#include #include #pragma comment(lib, "ws2_32.lib")

//不要安全檢測

#define _crt_secure_no_warnings

int main()

sockaddr_in addrsrv;

addrsrv.sin_family = af_inet;

addrsrv.sin_port = htons(5099);//http預設埠

addrsrv.sin_addr.s_un.s_addr = inet_addr("127.0.0.1");

= inet_addr("127.0.0.1");//htonl(inaddr_any); //伺服器位址為inaddr_any,即為(0.0.0.0)上監聽(任意ip),監聽埠為9990

//建立套接字

socket sockclient = socket(af_inet, sock_stream, 0);

if (socket_error == sockclient)

//向伺服器發出連線請求

if (connect(sockclient, (struct sockaddr*)&addrsrv, sizeof(addrsrv)) == invalid_socket)

int irecvlen = 0;

//傳送資料

char* buffsend = "hello, this is a client....";

irecvlen = send(sockclient, buffsend, strlen(buffsend), 0);

//接收資料

irecvlen = recv(sockclient, buff, sizeof(buff), 0);

printf("%s\n", buff);

//關閉套接字

closesocket(sockclient);

wsacleanup();

system("pause");

return 0;

}

參考文章及書籍

windows下的io模型之選擇(select)模型

select模型的原理、優點、缺點

tcp之 select模型

select與阻塞和非阻塞

《windows網路程式設計(第二版)》

socket程式設計使用poll替換select

poll函式在處理併發時,無fd setsize限制 伺服器端 include include include include include include 使用signal函式 include 使用wait函式 include include include include include de...

Windows網路程式設計

1.先總結一些會用到的知識 中計算機都分配乙個位址,該位址是乙個 32位的數值表示 客戶端和伺服器通訊的時候需要指定乙個 ip位址 和埠。ip位址 一般是用 internet標準 點分表示法 像a.b.c.d 一樣指定 的,每乙個字母代表乙個位元組的數字 十進位制 八進位制 或十六進製制 從左到右分...

windows網路程式設計

winsock是windows系統下利用socket套接字進行網路程式設計的相關函式,是windows下的網路程式設計介面。winsock在常見的windows平台上有兩個主要的版本,即winsock1和winsock2。編寫與winsock1相容的程式你需要引用標頭檔案winsock.h,如果編寫...