閉塞モードでsocket接続connectがタイムアウトしたら75秒になりますが、どうやって避けるべきですか?
9648 ワード
まとめ:非閉塞を設定し、接続が成功したかどうかを確認して、セットしてから閉塞モードを設定します。
selectの最初のパラメータは必ず1を追加します。そうでないと、ディスクリプタはちょうどセットの中にいないので、タイムアウトして0を返します。書いてはいけませんが、send、recvが正常な場合があります。
実例を見てからセレクトの定義を見ます。
server:
zjy@ubuntu:~$
ret:-1
ret:1
recv:
sock is not readable
sock is writable
buf size:10,ret:10
zjy@ubuntu:~$
selectは結果を1に返します。書いても読めません。
2、クライアントは、fdが読み書き可能かどうかを判断する前に、時間を3秒延長する。
zjy@ubuntu:~$/server
wait accept…
IP:127.1.0.1、ポルトガル:56006
read msg…
msg:
ddddddrecv msg size:10、total size:10
read msg…
msg:
recv msg size:0、total size:10
close connect…
wait accept…
wait accept…
^C
zjy@ubuntu:~$
zjy@ubuntu:~$
ret:-1
ret:2
recv:hello
sock is readable
sock is writable
buf size:10,ret:10
recv:hello
sock is readable
zjy@ubuntu:~$
selectの戻り値は2で、fdは書き込み可能です。
次のselectの関連定義は以下の通りです。http://www.cnblogs.com/wenqiang/p/5508541.html
selectは一般的にsocketネットワークプログラミングに使われています。ネットワークプログラミングの過程で、多くの閉塞の関数が発生します。ネットワークプログラミングの時に使うrecv、recvfrom、connect関数は閉塞の関数です。関数がうまく実行できない時、プログラムはずっとここでブロックされています。次のコードを実行できません。これは渋滞していないプログラミング方式を使う必要があります。selcet関数を使って、非ブロッキングプログラミングを実現できます。selcet関数はラウンド関数です。つまり、ファイルノードにループ問い合わせをするとタイムアウト時間を設定できます。タイムアウト時間が来たらコードをスキップして続けます。
select()は、一つ以上のインターフェースの状態を決定し、この関数は、一つ以上のインターフェースの状態を決定するために使用され、各セットのインターフェースに対して、スケジューラは、その可読性、書き込み可能性、およびエラー状態情報を調べ、fd_を使用することができる。set構造は検査待ちセットインターフェースのセットを表しています。戻りを呼び出すと、この構造は一定の条件を満たすセットインターフェースグループのサブセットがあり、条件を満たすセットインターフェースの数を返します。
通常はselectを用いて多重化を実現し、つまり複数のファイル記述子を同時に傍受することができる。
以下はselectの関数プロトタイプです。
最初のパラメータ:int nfds-->は、セット内のすべてのファイル記述子の範囲、すなわち、すべてのファイル記述子の最大値に1を加算する整数値です。
第二パラメータ:fd_set*readfds-->読み取り可能なファイル記述のセットを確認するために使用されます。
第三パラメータ:fd_set*writefds-->書き込み可能なファイルのセットを確認するために使用されます。
四番目のパラメータ:fd_set*exceptfds-->ファイルの記述子が異常かどうかを確認するために使用されます。
5番目のパラメータ:s reuct timeval*timeout-->はタイムアウト時間を設定するための時間構造体です。
timeout:最大待ち時間、渋滞操作はNULLです。
select関数の戻り値 負の値:selectエラーの正の値:いくつかのファイルが読み取り可能または書き込み可能な0を表します。タイムアウト待ちで、書き込み可能またはエラーのファイルがありません。
以下はselectと一緒に使う関数と構造の役割です。
selectの最初のパラメータは必ず1を追加します。そうでないと、ディスクリプタはちょうどセットの中にいないので、タイムアウトして0を返します。書いてはいけませんが、send、recvが正常な場合があります。
実例を見てからセレクトの定義を見ます。
server:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
struct sockaddr_in serAddr;
int listenSock, cnntSock;
listenSock = socket(AF_INET, SOCK_STREAM, 0);
serAddr.sin_family = AF_INET;
serAddr.sin_addr.s_addr = INADDR_ANY;
serAddr.sin_port = htons(1270);
bind(listenSock, (const struct sockaddr *)&serAddr, sizeof(sockaddr_in));
listen(listenSock, 10);
struct timeval tv = {3,0};//3s
setsockopt(listenSock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
struct sockaddr_in cliAddr;
socklen_t len = sizeof(sockaddr_in);
while (1)
{
memset(&cliAddr, 0, sizeof(cliAddr));
cout << "wait accept..." << endl;
cnntSock = accept(listenSock, (struct sockaddr*)&cliAddr, &len);
if (0 == cliAddr.sin_port)
continue;
cout<< "IP:" <
client:#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int sockClient = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSrv;
addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(1270);
struct timeval tv = {3,0};//3s
setsockopt(sockClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
int flag = fcntl(sockClient, F_GETFL, 0);
flag |= O_NONBLOCK;
fcntl(sockClient, F_SETFL, flag);
int ret = connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));
printf("ret:%d
", ret);
fd_set rfd, wfd;
FD_ZERO(&rfd);
FD_ZERO(&wfd);
FD_SET(sockClient, &rfd);
FD_SET(sockClient, &wfd);
ret = select(sockClient+1, &rfd, &wfd, NULL, &tv);
printf("ret:%d
", ret);
sleep(3);
if (FD_ISSET(sockClient, &rfd))
{
char buf[1024] = {0};
recv(sockClient, buf, 1024, 0);
printf("recv:%s
", buf);
printf("sock is readable
");
}
else
{
char buf[1024] = {0};
recv(sockClient, buf, 1024, 0);
printf("recv:%s
", buf);
printf("sock is not readable
");
}
if (FD_ISSET(sockClient, &wfd))
printf("sock is writable
");
else
{
printf("sock is not writable
");
}
flag = fcntl(sockClient, F_GETFL, 0);
flag &= ~O_NONBLOCK;
fcntl(sockClient, F_SETFL, flag);
char buf[10] = {0};
for(unsigned int i = 0; i < 10; i++)
{
buf[i] = 'd';
}
ret = send(sockClient, buf, sizeof(buf) , 0);
cout << "buf size:" << sizeof(buf) << ",ret:" << ret <
1、クライアントは、fdが読み書き可能かどうかを判断する前に、時間を延長しないで3秒。zjy@ubuntu:~$
ret:-1
ret:1
recv:
sock is not readable
sock is writable
buf size:10,ret:10
zjy@ubuntu:~$
selectは結果を1に返します。書いても読めません。
2、クライアントは、fdが読み書き可能かどうかを判断する前に、時間を3秒延長する。
zjy@ubuntu:~$/server
wait accept…
IP:127.1.0.1、ポルトガル:56006
read msg…
msg:
ddddddrecv msg size:10、total size:10
read msg…
msg:
recv msg size:0、total size:10
close connect…
wait accept…
wait accept…
^C
zjy@ubuntu:~$
zjy@ubuntu:~$
ret:-1
ret:2
recv:hello
sock is readable
sock is writable
buf size:10,ret:10
recv:hello
sock is readable
zjy@ubuntu:~$
selectの戻り値は2で、fdは書き込み可能です。
次のselectの関連定義は以下の通りです。http://www.cnblogs.com/wenqiang/p/5508541.html
selectは一般的にsocketネットワークプログラミングに使われています。ネットワークプログラミングの過程で、多くの閉塞の関数が発生します。ネットワークプログラミングの時に使うrecv、recvfrom、connect関数は閉塞の関数です。関数がうまく実行できない時、プログラムはずっとここでブロックされています。次のコードを実行できません。これは渋滞していないプログラミング方式を使う必要があります。selcet関数を使って、非ブロッキングプログラミングを実現できます。selcet関数はラウンド関数です。つまり、ファイルノードにループ問い合わせをするとタイムアウト時間を設定できます。タイムアウト時間が来たらコードをスキップして続けます。
select()は、一つ以上のインターフェースの状態を決定し、この関数は、一つ以上のインターフェースの状態を決定するために使用され、各セットのインターフェースに対して、スケジューラは、その可読性、書き込み可能性、およびエラー状態情報を調べ、fd_を使用することができる。set構造は検査待ちセットインターフェースのセットを表しています。戻りを呼び出すと、この構造は一定の条件を満たすセットインターフェースグループのサブセットがあり、条件を満たすセットインターフェースの数を返します。
通常はselectを用いて多重化を実現し、つまり複数のファイル記述子を同時に傍受することができる。
以下はselectの関数プロトタイプです。
1 /* According to POSIX.1-2001 */
2 #include select.h>
3
4 int select(int nfds, fd_set *readfds, fd_set *writefds,
5 fd_set *exceptfds, struct timeval *timeout);
具体的に説明します。最初のパラメータ:int nfds-->は、セット内のすべてのファイル記述子の範囲、すなわち、すべてのファイル記述子の最大値に1を加算する整数値です。
第二パラメータ:fd_set*readfds-->読み取り可能なファイル記述のセットを確認するために使用されます。
第三パラメータ:fd_set*writefds-->書き込み可能なファイルのセットを確認するために使用されます。
四番目のパラメータ:fd_set*exceptfds-->ファイルの記述子が異常かどうかを確認するために使用されます。
5番目のパラメータ:s reuct timeval*timeout-->はタイムアウト時間を設定するための時間構造体です。
timeout:最大待ち時間、渋滞操作はNULLです。
select関数の戻り値 負の値:selectエラーの正の値:いくつかのファイルが読み取り可能または書き込み可能な0を表します。タイムアウト待ちで、書き込み可能またはエラーのファイルがありません。
以下はselectと一緒に使う関数と構造の役割です。
1 void FD_CLR(int fd, fd_set *set);//
2 int FD_ISSET(int fd, fd_set *set);//
3 void FD_SET(int fd, fd_set *set);// ;
4 void FD_ZERO(fd_set *set);//
struct timeval構造はタイムアウト時間を設定するために使われています。この構造体は正確に秒とミリ秒までできます。1 struct timeval {
2 time_t tv_sec; /* seconds */
3 suseconds_t tv_usec; /* microseconds */
4 };