對於類項目,我們被指示使用Winsock2創建簡單的程序。我創建了一個開始的回聲程序,現在我試圖實現一種方法,讓程序在一個房間內找到主機本身。該房間位於專用網絡192.168.xxx.xxx上,子網數量增加10個,並且可以運行服務器的計算機在每個子網上都是數字50,51和52。我打算做一個簡單的實現,只是試圖連接到每臺計算機,如果可以的話,它就是服務器。不是最好的解決方案,但它仍然使用Winsock2,它適用於我。使用Winsock2和C縮短TCP連接的等待時間
SOCKET connectsock(const char *host, const char *service, const char *transport)
{
struct hostent *phe; /* pointer to host information entry */
struct servent *pse; /* pointer to service information entry */
struct protoent *ppe; /* pointer to protocol information entry*/
struct sockaddr_in sin; /* an Internet endpoint address */
int s, type; /* socket descriptor and socket type */
while (1)
{
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
/* Map service name to port number */
if (pse = getservbyname(service, transport))
sin.sin_port = pse->s_port;
else if ((sin.sin_port = htons((u_short)atoi(service))) == 0)
errexit("can't get \"%s\" service entry\n", service);
/* Map host name to IP address, allowing for dotted decimal */
if (phe = gethostbyname(host))
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit("can't get \"%s\" host entry\n", host);
/* Map protocol name to protocol number */
if ((ppe = getprotobyname(transport)) == 0)
errexit("can't get \"%s\" protocol entry\n", transport);
/* Use protocol to choose a socket type */
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
errexit("can't create socket: %d\n", GetLastError());
/* Connect the socket */
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("can't connect to %s.%s: %d\n", host, service, GetLastError());
host = "localhost";
}
else
break;
}
return s;
}
這個循環工作正常,並簡單地連接到第一個IP地址,192.168.10.50,然後如果它拉一個錯誤,連接到一個主機,如果另一個錯誤,它會嘗試第三主機,所以等等,直到它連接成功。由於我仍然只測試程序,我只是重定向到第一次失敗後連接到本地主機。
它的工作原理完全正確,唯一的問題是在課堂上,沒有延遲。因此,如果有的話,連接會發生十分之一秒。默認情況下,程序將嘗試連接到第一臺計算機,但無法進入,但在切換到下一個主機之前,它會等待5秒鐘並等待響應。
由於這是一個封閉的互聯網內的小規模計劃,我應該沒有任何問題,等待時間縮短到半秒鐘,但我的問題是如何?
是否有可能,如果沒有,我該怎麼做才能糾正它?有沒有更高效的方法讓主機找到可以移動的服務器?服務器將更換電腦。
您可以將您的請求並行化爲大量線程池,也可以使用非阻塞套接字。使用非阻塞套接字,您可以嘗試在單個線程中連接,跟蹤您創建的所有SOCKET,然後在一兩秒鐘後查找有效SOCKET。 – Kaslai
所以你認爲我應該開始像3線程左右,每個嘗試不同的地址? 非阻塞套接字如何?你能給我更多的信息嗎? – Brian5193
在SOCKET上使用'ioctlsocket'可以用來更改套接字屬性。 'u_long iMode = 1; ioctlsocket(Socket,FIONBIO和iMode);'將使套接字非阻塞,其中'Socket'是你的SOCKET對象。非阻塞套接字操作只是立即返回,因此您可以使用打開但不完整的連接填充SOCKET數組。 – Kaslai