當前位置:首頁 » 編程軟體 » 網路編程select

網路編程select

發布時間: 2022-07-15 02:33:56

java的selector網路編程:怎樣給特定channel發信息

如果不需要考慮網路安全之類的話,全頻公放好了,將前幾個位元組設為客戶端代號,消息到達各客戶端的時候,客戶端自己對照自己的代號,如果是,則對消息進行相關處理,如果不是,略過,等待下一條信息的接收
一個人對一個人的:消息帶著代號傳到伺服器,伺服器全頻廣播,只有要發送的對象發現是給自己的,處理,其他人略過
一個人對所有人:消息不帶代號,即前幾個位元組設為特定數值,伺服器全頻廣播,各客戶端發現是所有人的,開始處理
這樣一來就非常好實現了,不涉及復雜結構

② c++網路編程中,究竟什麼是非同步IO 還有那個select函數是非同步IO

基本一樣,JAVA現在用的多,大型開發環境

③ IO模型及select,poll,epoll和kqueue的區別

(一)首先,介紹幾種常見的I/O模型及其區別,如下:
blocking I/O
nonblocking I/O
I/O multiplexing (select and poll)
signal driven I/O (SIGIO)
asynchronous I/O (the POSIX aio_functions)—————非同步IO模型最大的特點是 完成後發回通知。
阻塞與否,取決於實現IO交換的方式。
非同步阻塞是基於select,select函數本身的實現方式是阻塞的,而採用select函數有個好處就是它可以同時監聽多個文件句柄.
非同步非阻塞直接在完成後通知,用戶進程只需要發起一個IO操作然後立即返回,等IO操作真正的完成以後,應用程序會得到IO操作完成的通知,此時用戶進程只需要對數據進行處理就好了,不需要進行實際的IO讀寫操作,因為真正的IO讀取或者寫入操作已經由內核完成了。

1 blocking I/O
這個不用多解釋吧,阻塞套接字。下圖是它調用過程的圖示:

重點解釋下上圖,下面例子都會講到。首先application調用 recvfrom()轉入kernel,注意kernel有2個過程,wait for data和 data from kernel to user。直到最後 complete後,recvfrom()才返回。此過程一直是阻塞的。

2 nonblocking I/O:
與blocking I/O對立的,非阻塞套接字,調用過程圖如下:

可以看見,如果直接操作它,那就是個輪詢。。直到內核緩沖區有數據。

3 I/O multiplexing (select and poll)
最常見的I/O復用模型,select。

select先阻塞,有活動套接字才返回。與blocking I/O相比,select會有兩次系統調用,但是select能處理多個套接字。

4 signal driven I/O (SIGIO)
只有UNIX系統支持,感興趣的課查閱相關資料

與I/O multiplexing (select and poll)相比,它的優勢是,免去了select的阻塞與輪詢,當有活躍套接字時,由注冊的handler處理。

5 asynchronous I/O (the POSIX aio_functions)
很少有*nix系統支持,windows的IOCP則是此模型

完全非同步的I/O復用機制,因為縱觀上面其它四種模型,至少都會在由kernel data to appliction時阻塞。而該模型是當完成後才通知application,可見是純非同步的。好像只有windows的完成埠是這個模型,效率也很出色。
6 下面是以上五種模型的比較

可以看出,越往後,阻塞越少,理論上效率也是最優。
=====================分割線==================================
5種模型的比較比較清晰了,剩下的就是把select,epoll,iocp,kqueue按號入座那就OK了。
select和iocp分別對應第3種與第5種模型,那麼epoll與kqueue呢?其實也於select屬於同一種模型,只是更高級一些,可以看作有了第4種模型的某些特性,如callback機制。
為什麼epoll,kqueue比select高級?
答案是,他們無輪詢。因為他們用callback取代了。想想看,當套接字比較多的時候,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費很多CPU時間。如果能給套接字注冊某個回調函數,當他們活躍時,自動完成相關操作,那就避免了輪詢,這正是epoll與kqueue做的。
windows or *nix (IOCP or kqueue/epoll)?

誠然,Windows的IOCP非常出色,目前很少有支持asynchronous I/O的系統,但是由於其系統本身的局限性,大型伺服器還是在UNIX下。而且正如上面所述,kqueue/epoll 與 IOCP相比,就是多了一層從內核數據到應用層的阻塞,從而不能算作asynchronous I/O類。但是,這層小小的阻塞無足輕重,kqueue與epoll已經做得很優秀了。
提供一致的介面,IO Design Patterns
實際上,不管是哪種模型,都可以抽象一層出來,提供一致的介面,廣為人知的有ACE,Libevent(基於reactor模式)這些,他們都是跨平台的,而且他們自動選擇最優的I/O復用機制,用戶只需調用介面即可。說到這里又得說說2個設計模式,Reactor and Proactor。見:Reactor模式--VS--Proactor模式。Libevent是Reactor模型,ACE提供Proactor模型。實際都是對各種I/O復用機制的封裝。
Java nio包是什麼I/O機制?
現在可以確定,目前的java本質是select()模型,可以檢查/jre/bin/nio.dll得知。至於java伺服器為什麼效率還不錯。。我也不得而知,可能是設計得比較好吧。。-_-。
=====================分割線==================================
總結一些重點:
只有IOCP是asynchronous I/O,其他機制或多或少都會有一點阻塞。
select低效是因為每次它都需要輪詢。但低效也是相對的,視情況而定,也可通過良好的設計改善
epoll, kqueue、select是Reacor模式,IOCP是Proactor模式。
java nio包是select模型。。
(二)epoll 與select的區別

1. 使用多進程或者多線程,但是這種方法會造成程序的復雜,而且對與進程與線程的創建維護也需要很多的開銷。(Apache伺服器是用的子進程的方式,優點可以隔離用戶) (同步阻塞IO)

2.一種較好的方式為I/O多路轉接(I/O multiplexing)(貌似也翻譯多路復用),先構造一張有關描述符的列表(epoll中為隊列),然後調用一個函數,直到這些描述符中的一個准備好時才返回,返回時告訴進程哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案,select為POSIX標准中的,而epoll為linux所特有的。

區別(epoll相對select優點)主要有三:
1.select的句柄數目受限,在linux/posix_types.h頭文件有這樣的聲明:#define __FD_SETSIZE 1024 表示select最多同時監聽1024個fd。而epoll沒有,它的限制是最大的打開文件句柄數目。

2.epoll的最大好處是不會隨著FD的數目增長而降低效率,在selec中採用輪詢處理,其中的數據結構類似一個數組的數據結構,而epoll是維護一個隊列,直接看隊列是不是空就可以了。epoll只會對"活躍"的socket進行操作---這是因為在內核實現中epoll是根據每個fd上面的callback函數實現的。那麼,只有"活躍"的socket才會主動的去調用 callback函數(把這個句柄加入隊列),其他idle狀態句柄則不會,在這點上,epoll實現了一個"偽"AIO。但是如果絕大部分的I/O都是「活躍的」,每個I/O埠使用率很高的話,epoll效率不一定比select高(可能是要維護隊列復雜)。

3.使用mmap加速內核與用戶空間的消息傳遞。無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很重要,在這點上,epoll是通過內核於用戶空間mmap同一塊內存實現的。

關於epoll工作模式ET,LT

epoll有兩種工作方式
ET:Edge Triggered,邊緣觸發。僅當狀態發生變化時才會通知,epoll_wait返回。換句話,就是對於一個事件,只通知一次。且只支持非阻塞的socket。
LT:Level Triggered,電平觸發(默認工作方式)。類似select/poll,只要還有沒有處理的事件就會一直通知,以LT方式調用epoll介面的時候,它就相當於一個速度比較快的poll.支持阻塞和不阻塞的socket。

三 Linux並發網路編程模型

1 Apache 模型,簡稱 PPC ( Process Per Connection ,):為每個連接分配一個進程。主機分配給每個連接的時間和空間上代價較大,並且隨著連接的增多,大量進程間切換開銷也增長了。很難應對大量的客戶並發連接。
2 TPC 模型( Thread Per Connection ):每個連接一個線程。和PCC類似。
3 select 模型:I/O多路復用技術。
.1 每個連接對應一個描述。select模型受限於 FD_SETSIZE即進程最大打開的描述符數linux2.6.35為1024,實際上linux每個進程所能打開描數字的個數僅受限於內存大小,然而在設計select的系統調用時,卻是參考FD_SETSIZE的值。可通過重新編譯內核更改此值,但不能根治此問題,對於百萬級的用戶連接請求 即便增加相應 進程數, 仍顯得杯水車薪呀。
.2select每次都會掃描一個文件描述符的集合,這個集合的大小是作為select第一個參數傳入的值。但是每個進程所能打開文件描述符若是增加了 ,掃描的效率也將減小。
.3內核到用戶空間,採用內存復制傳遞文件描述上發生的信息。
4 poll 模型:I/O多路復用技術。poll模型將不會受限於FD_SETSIZE,因為內核所掃描的文件 描述符集合的大小是由用戶指定的,即poll的第二個參數。但仍有掃描效率和內存拷貝問題。
5 pselect模型:I/O多路復用技術。同select。
6 epoll模型:
.1)無文件描述字大小限制僅與內存大小相關
.2)epoll返回時已經明確的知道哪個socket fd發生了什麼事件,不用像select那樣再一個個比對。
.3)內核到用戶空間採用共享內存方式,傳遞消息。
四 :FAQ
1、單個epoll並不能解決所有問題,特別是你的每個操作都比較費時的時候,因為epoll是串列處理的。 所以你有還是必要建立線程池來發揮更大的效能。
2、如果fd被注冊到兩個epoll中時,如果有時間發生則兩個epoll都會觸發事件。
3、如果注冊到epoll中的fd被關閉,則其會自動被清除出epoll監聽列表。
4、如果多個事件同時觸發epoll,則多個事件會被聯合在一起返回。
5、epoll_wait會一直監聽epollhup事件發生,所以其不需要添加到events中。
6、為了避免大數據量io時,et模式下只處理一個fd,其他fd被餓死的情況發生。linux建議可以在fd聯繫到的結構中增加ready位,然後epoll_wait觸發事件之後僅將其置位為ready模式,然後在下邊輪詢ready fd列表。

④ c++網路編程中~~~究竟什麼是非同步IO 還有那個select函數是非同步IO

非同步文件IO也就是重疊IO。
在同步文件IO中,線程啟動一個IO操作然後就立即進入等待狀態,直到IO操作完成後才醒來繼續執行。而非同步文件IO方式中,線程發送一個IO請求到內核,然後繼續處理其他的事情,內核完成IO請求後,將會通知線程IO操作完成了。
如果IO請求需要大量時間執行的話,非同步文件IO方式可以顯著提高效率,因為在線程等待的這段時間內,CPU將會調度其他線程進行執行,如果沒有其他線程需要執行的話,這段時間將會浪費掉(可能會調度操作系統的零頁線程)。如果IO請求操作很快,用非同步IO方式反而還低效,還不如用同步IO方式。
同步IO在同一時刻只允許一個IO操作,也就是說對於同一個文件句柄的IO操作是序列化的,即使使用兩個線程也不能同時對同一個文件句柄同時發出讀寫操作。重疊IO允許一個或多個線程同時發出IO請求。
非同步IO在請求完成時,通過將文件句柄設為有信號狀態來通知應用程序,或者應用程序通過GetOverlappedResult察看IO請求是否完成,也可以通過一個事件對象來通知應用程序。
例如DeviceIoControl這個函數,他就可以通過參數指定是同步或非同步,如果是同步的話,則該函數將會等待結果返回後,才執行下一條語句。如果是非同步的話,DeviceIoControl調用後馬上返回,如果參數正確,則回返回ERROR_IO_PENDING(忘了怎樣寫,不過肯定是有PENDING這個詞),然後你可以通過GetOverlappedResult獲取返回結果,是一個overlap結構,是在你調用DeviceIoControl的最後一個參數傳進去的``
簡單的說``同步在編程里,一般是指某個操作執行完後,才可以執行後面的操作``拿到IO上來說``就是我要做完這個IO操作``才繼續後面的操作```
非同步則是,我交帶了某個操作給系統(可以是windows,也可以是你自己的庫),我呆會過來拿,我現在要去忙別的``拿到IO上說``我交帶了某個IO操作給系統。。。。。

⑤ 如何使用windows網路編程select

1. select系統調用
select系統調用是用來讓我們的程序監視多個文件描述符的狀態變化的。程序會停在select這里等待,直到被監視的文件描述符有某一個或多個發生了狀態改變。
select()的機制中提供一fd_set的數據結構,實際上是一long類型的數組,每一個數組元素都能與一打開的文件句柄建立聯系,建立聯系的工作由程序員完成,當調用select()時,由內核根據IO狀態修改fd_set的內容,由此來通知執行了select()的進程哪些Socket或文件可讀可寫。
select函數原型:
#include <sys/select.h> #include <sys/time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);
ndfs:select監視的文件句柄數,視進程中打開的文件數而定,一般設為要監視各文件中的最大文件描述符值加1。
readfds:這個文件描述符集合監視文件集中的任何文件是否有數據可讀,當select函數返回的時候,readfds將清除其中不可讀的文件描述符,只留下可讀的文件描述符。
writefds:這個文件描述符集合監視文件集中的任何文件是否有數據可寫,當select函數返回的時候,writefds將清除其中不可寫的文件描述符,只留下可寫的文件描述符。
exceptfds:這個文件集將監視文件集中的任何文件是否發生錯誤,其實,它可用於其他的用途,例如,監視帶外數據OOB,帶外數據使用MSG_OOB標志發送到套接字上。當select函數返回的時候,exceptfds將清除其中的其他文件描述符,只留下標記有OOB數據的文件描述符。
timeout:本次select()的超時結束時間。這個參數至關重要,它可以使select處於三種狀態:
(1)若將NULL以形參傳入,即不傳入時間結構,就是將select置於阻塞狀態,一定等到監視文件描述符集合中某個文件描述符發生變化為止;
(2)若將時間值設為0秒0毫秒,就變成一個純粹的非阻塞函數,不管文件描述符是否有變化,都立刻返回繼續執行,文件無變化返回0,有變化返回一個正值;
(3)timeout的值大於0,這就是等待的超時時間,即select在timeout時間內阻塞,超時時間之內有事件到來就返回了,否則在超時後不管怎樣一定返回,返回值同上述。
函數的返回值:
正值:表示監視的文件集中有文件描述符符合要求
零值:表示select監視超時
負值:表示發生了錯誤,錯誤值由errno指定。
宏操作:
FD_ZERO(fd_set *set): 用來清除描述片語set的全部位
FD_SET(int fd,fd_set*set): 用來設置描述片語set中相關fd的位
FD_ISSET(int fd,fd_set *set): 用來測試描述片語set中相關fd 的位是否為真
FD_CLR(inr fd,fd_set* set): 用來清除描述片語set中相關fd 的位注意事項:
(1)對於可寫性的檢查,最好放在需要寫數據的時候進行檢查。如果和可讀性放在同一個地方進行檢查,那麼select很可能每次都會因為可寫性檢查成功而返回。
(2)select()調用會清空傳遞給它的集合參數中的內容,也就是會清空readfds、writefd、exceptfds這三個指針參數所指定的描述符集合。因此,在每次調用select()之前,必須重新初始化並把需要監視的描述符填寫到相應的描述符集合中。select()調用也會清空timeout指針所指向的struct timeval結構,所以在每次調用select()之前也要重新填充timeout指針所指向的struct timeval結構。

⑥ 網路編程中,select模型是否要重置fet_set狀態

select是需要重置set的:

intselect(intmaxfdp1,fd_set*readfds,
fd_set*writefds,fd_set*exceptfds,
structtimeval*tvptr);

可以參閱《Advanced Programming in the UNIX Environment》,或者具體平台的manual。

通俗的說readfds, writefds, exceptfds即做「輸入參數」,也做「輸出參數」,就是傳進去後會對應的fd_set被修改。

比如APUE上寫到:

There are three possible return values from select.

1. A return value of &#8722;1 means that an error occurred. This can happen, for

example, if a signal is caught before any of the specified descriptors are ready.

In this case, none of the descriptor sets will be modified.

2. A return value of 0 means that no descriptors are ready. This happens if the

time limit expires before any of the descriptors are ready. When this happens,

all the descriptor sets will be zeroed out.

3. A positive return value specifies the number of descriptors that are ready. This

value is the sum of the descriptors ready in all three sets, so if the same

descriptor is ready to be read and written, it will be counted twice in the return

value. The only bits left on in the three descriptor sets are the bits

corresponding to the descriptors that are ready.

其中2.的最後一句就提到:如果select只是因為timeout到了,所有(readfds, writefds, exceptfds)都會被置為空。

⑦ Python網路編程中替代select模塊的方法有哪些

、導入模塊
import mole
from mole.xx import xx
from mole.xx import xx as rename
from mole.xx import *
二、源模塊
yum、pip、apt-get
源碼編譯安裝:Python setup.py build Python setup install
三、用模塊
os模塊#用作系統級別工作
sys模塊#提供解釋器相關操作
hashlib模塊# 用於加密相關操作
jsonpickle模塊 #用於序列化數據
subprocess模塊
shuit模塊 #文件復制移
logging模塊#格式化記錄志
random模塊 用於取隨機數
time datetime模塊間模塊
re模塊 則匹配

⑧ java網路編程寫一個基礎的小程序一直提示 java.net.SocketException: select failed

據上面顯示的是:連接失敗
可能是連接語句出錯了,好好檢查一下細節方面
例如:
伺服器端需要指定一個確定的埠號來創建創建伺服器對象
Socket socket = new Socket("168.150.12.53",9999);

並用此埠號進行監聽。。

Socket s = server.accept() ; // 監聽窗口,等待連接

或:

Socket socket = new Socket(InetAddress.getLocalHost(),5678); // 向主機名為InetAddress.getLocalHost()的伺服器申請連接

客戶端需用伺服器所在機器的ip以及伺服器的埠作為參數創建一個Socket對象
Socket socket = new Socket("168.160.12.42",9998);
或:
Socket socket = new Socket(InetAddress.getLocalHost(),5678); // 向主機名為InetAddress.getLocalHost()的伺服器申請連接

⑨ linux網路編程,可以用select函數代替accept函數接收客戶端的connect請求嗎

select不可以替代accept,但可以用來作輔助,比如
nfds = select(Fd + 1, &fds, NULL, NULL , &tv);
if(nfds>0){
if (listenSock != -1 && FD_ISSET(listenSock, &fds))
{

if ((sock = accept(listenSock,(struct sockaddr *)&addr, &addrlen)) < 0)
{
return -1;
}
}
}
大概就這樣

⑩ 網路編程中select函數如何接受一個accept事件

#include <winsock.h>

#include <stdio.h>

#define PORT 5150 //埠

#define MSGSIZE 1024 //信息大小

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

int g_iTotalConn = 0; //連接數量

SOCKET g_CliSocketArr[FD_SETSIZE]; //套接字數組

DWORD WINAPI WorkerThread(LPVOID lpParameter);//線程函數

int main()

{

WSADATA wsaData;

SOCKET sListen, sClient;

SOCKADDR_IN local, client;

int iaddrSize = sizeof(SOCKADDR_IN);

DWORD dwThreadId;

// Initialize Windows socket library

//裝載套接字型檔

WSAStartup(0x0202, &wsaData);

// Create listening socket

//創建套接字

sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// Bind

//綁定

local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

local.sin_family = AF_INET;

local.sin_port = htons(PORT);

bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));

// Listen

//監聽

listen(sListen, 3);

// Create worker thread

//創建線程

CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);

while (TRUE)

{

// Accept a connection

//接受一個連接,返回的是客戶套的套接字

sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);

//這里client的SOCKADDR_IN client 中可以取出IP

printf("Accepted client:%s:%d ", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

// Add socket to g_CliSocketArr

//把客戶端套接字放入數組中

g_CliSocketArr[g_iTotalConn++] = sClient;

}

return 0;

}


DWORD WINAPI WorkerThread(LPVOID lpParam)//線程

{

int i;

fd_set fdread;//結構

int ret;

struct timeval tv = {1, 0};//超時時間 SELECT模型中用到的這里是1秒

char szMessage[MSGSIZE];//信息數組,事實上就是個緩沖區

while (TRUE)

{

FD_ZERO(&fdread);//清空fd_set結構

for (i = 0; i < g_iTotalConn; i++)

{

FD_SET(g_CliSocketArr[i], &fdread);//把客戶套接字放到SELECT要求的數組中

}

//**************************************

// We only care read event

//只關心讀的情況

ret = select(0, &fdread, NULL, NULL, &tv);

if (ret == 0)

{

// Time expired 超時

continue;

}

//如果SELECT返回不是0

for (i = 0; i < g_iTotalConn; i++)

{

if (FD_ISSET(g_CliSocketArr[i], &fdread))

{

// A read event happened on g_CliSocketArr[i]

//一個可讀發生在這個套接字上

ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);

//把它讀出到緩沖區

if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))

{

// Client socket closed

//客戶端關閉

printf("Client socket %d closed. ", g_CliSocketArr[i]);

closesocket(g_CliSocketArr[i]);//關閉這個套接字

if (i < g_iTotalConn - 1)

{

//將數組中最後一個套接字挪到當前的位置上

g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];

}

}

else

{

// We received a message from client

//如果以上沒發生,那麼就接收到一個客戶端的信息

szMessage[ret] = '';

//直接回送回去

send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);

}

}

}

}

return 0;

}


熱點內容
安卓怎麼關閉藍牙自動連接 發布:2024-09-08 10:58:12 瀏覽:11
tsm伺服器修改ip地址 發布:2024-09-08 10:21:06 瀏覽:615
共享雲源碼 發布:2024-09-08 10:01:10 瀏覽:397
ios應用上傳 發布:2024-09-08 09:39:41 瀏覽:441
ios儲存密碼哪裡看 發布:2024-09-08 09:30:02 瀏覽:874
opensslcmake編譯 發布:2024-09-08 09:08:48 瀏覽:653
linux下ntp伺服器搭建 發布:2024-09-08 08:26:46 瀏覽:744
db2新建資料庫 發布:2024-09-08 08:10:19 瀏覽:173
頻率計源碼 發布:2024-09-08 07:40:26 瀏覽:780
奧迪a6哪個配置帶後排加熱 發布:2024-09-08 07:06:32 瀏覽:101