Giriş
Açıklaması şöyle
Seri iletişim için şöyle yaparız.
fd_set
select çağrısı sonucunda fd_set değişir. Bu yüzden çağrıdan önce fd_set izlenmek istenen fd'ler için tekrar doldurulur. (rearm) Şöyle yaparız.
Bir socketin yazılabilir olması sanırım sadece TCP soketi için geçerli. UDP connectionless olduğu için socket her zaman yazılabilir durumda.
FD_ISSET macrosu
Eğer belli bir socketi kontrol etmek istersek şöyle yaparız.
select çağrı parametreleri
İlk parametre fd_set'e girilmiş en büyük socket değerinin bir fazlasıdır. İkinci parametre okunacak fd_set'i. Üçüncü parametre yazılacak fd_set'i, Dördüncü parametre exception fd_set'i, altıncı parametre is timeout değeridir.
select - timeout olmadan okuma
Timeout kullanmadan şöyle yaparız.
Çağrı sonucu -1 ise hata olmuştur.
Çağrı sonucu > 0 ise okunacak bir şey vardır.
Çağrı sonucu 0 ise timeout olmuştur.
Örnek
Şöyle yaparız.
Şöyle yaparız.
Açıklaması şöyle
select and poll does a linear search across the sockets, which does not scale very well.select () ile kullanılan socketler non-blocking olmak zorunda değil. Ancak ben non-blocking olmasını tercih ediyorum. Eğer socket okumak üzere hazır olarak görünse bile, hata olursa sadece EWOULDBLOCK koduna bakarak problemsiz çalışabiliriz. Java'da ise socketin non-blocking olması gerekir.
Seri iletişim için şöyle yaparız.
open (...,O_RDRW |O_NDELAY |O_NONBLOCK);
fd_set
Önce bir set tanımlanır.
fd_set sockSet;
FD_ZERO(&sockSet);
Daha sonra set'e izlemek istediğimiz fd'leri atarız. Bu çağrı her bir socket için tekrarlanır
FD_SET(fd1, &sockSet);
int maxfd = server_sock2 + 1;
FD_SET sockSet;
int ret;
while(1) {
// Setup SD_SET each time calling select
FD_ZERO(&read_fs);
FD_SET(server_sock1, &read_fs);
FD_SET(server_sock2, &read_fs);
if ((ret = select(maxfd+1,&readfds,NULL,NULL,NULL)) == -1) {
error("Err in select");
}
for(i = 0; i < maxfd && ret; i++, ret--) {
if(FD_ISSET(i, &readfds) {...}
}
}
Writable socketBir socketin yazılabilir olması sanırım sadece TCP soketi için geçerli. UDP connectionless olduğu için socket her zaman yazılabilir durumda.
FD_ISSET macrosu
Eğer belli bir socketi kontrol etmek istersek şöyle yaparız.
if(FD_ISSET(f1, &sockSet)) {
recv(f1, ..., ...);
}
FD_SET macrosu
İzlemek istediğimiz fd'yi fd_set yapısına ekler. Şöyle yaparız.
int server_sock = ...;
FD_SET sockSet;
FD_ZERO(&rsockSet);
FD_SET(server_sock, &sockSet
);
FD_ZERO macrosu
fd_set yapısını sıfırlar. Şöyle yaparız.
FD_SET sockSet;
FD_ZERO(&sockSet);
İlk parametre fd_set'e girilmiş en büyük socket değerinin bir fazlasıdır. İkinci parametre okunacak fd_set'i. Üçüncü parametre yazılacak fd_set'i, Dördüncü parametre exception fd_set'i, altıncı parametre is timeout değeridir.
Timeout kullanmadan şöyle yaparız.
if(select(maxfd+1, &read_fs, NULL, NULL, NULL))
{...}
select - timeout ile okuma
select çağrısı Linux'ta timeout değerini değiştirir. Bu yüzden her çağrıdan önce timeout değişkenini tekrar doldurmak gerekir. Açıklaması şöyle.Yani şöyle yaparız.On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1-2001 permits either behavior.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns.
while (1)
{
struct timeval tv = {1, 0};
int retval=select(maxfd+1,read_fs, NULL, NULL,&tv);
...
}
select çağrı sonucuÇağrı sonucu -1 ise hata olmuştur.
Çağrı sonucu > 0 ise okunacak bir şey vardır.
Çağrı sonucu 0 ise timeout olmuştur.
Örnek
Şöyle yaparız.
if (select(max_fd+1, &socketSet, NULL, NULL, &tv) > 0) {...}
ÖrnekŞöyle yaparız.
int result = select(max_fd + 1, &socketSet, NULL, NULL, &tv);
switch (select_result) {
case -1: //Error
...
case 0: //Timeout
...
default:
//DATA AVAILABLE
break;
}
Hiç yorum yok:
Yorum Gönder