在两个主机之间的udp中使用非阻塞读取时,我遇到了丢失消息的问题.发件人在linux上,读者在winxp上.python中的这个例子显示了这个问题.
以下是用于显示问题的三个脚本.
send.py:
import socket, sys
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
host = sys.argv[1]
s.sendto('A'*10, (host,8888))
s.sendto('B'*9000, (host,8888))
s.sendto('C'*9000, (host,8888))
s.sendto('D'*10, (host,8888))
s.sendto('E'*9000, (host,8888))
s.sendto('F'*9000, (host,8888))
s.sendto('G'*10, (host,8888))
Run Code Online (Sandbox Code Playgroud)
read.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('',8888))
while True:
data,address = s.recvfrom(10000)
print "recv:", data[0],"times",len(data)
Run Code Online (Sandbox Code Playgroud)
read_nb.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('',8888))
s.setblocking(0)
data =''
address = ''
while True:
try:
data,address = s.recvfrom(10000)
except socket.error:
pass
else:
print "recv:", data[0],"times",len(data)
Run Code Online (Sandbox Code Playgroud)
示例1(工作正常):
ubuntu> python send.py
winxp> read.py
从read.py得到这个ok结果:
recv:A次10次
recv:B次9000次
recv:C次9000次 …
连接到网络上的设备时出现问题.每当我调用getaddrinfo()时它返回11001.我已经在IP_ADDRESS字符串(Global Var)中检查了许多不同的IP.我用nslookup检查了所有非工作号码,大多数存在于那里.
getaddrinfo-returns-always-11001-host-not-found 似乎在问一个类似的问题,但那里没有答案.
目前,我的代码甚至没有尝试连接到远程设备,只是尝试解析IP.一旦有效,我就可以继续处理更大更混乱的问题.
执行:
int connectToDevice(char *sendbuf, char *recvbuf, SOCKET ConnectSocket)
{
WSADATA wsaData;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
struct timeval tval;
fd_set rset, wset;
int iResult;
u_long mode = -1;
//Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
//Resolve the server address and port
iResult = getaddrinfo(IP_ADDRESS, DEFAULT_PORT, …Run Code Online (Sandbox Code Playgroud) 我在Visual Studio 2010中编写程序.我无法链接ws2_32.dll以我的项目命名的文件.
谁能告诉我怎么做到这一点?
无论如何,不确定这是否是正确的地方.
我正在用c ++编写一个简单的聊天,其中客户端获取套接字值作为开头的昵称.
在Linux套接字只是文件描述符,他们得到他们的3,4,5 ...跟随stdin,stdout,stderr.
但我注意到在Win上,第一个客户端套接字总是获得值192,而其他客户端套接字则相差20(几乎总是).

所以这就是我的问题,为什么套接字在win平台上获得这样的价值(我的是win7 x64)?小小的谷歌搜索没有帮助.
提前致谢
WSAStringToAddress的Windows文档指出:
INT WSAAPI WSAStringToAddress(
_In_ LPTSTR AddressString,
_In_ INT AddressFamily,
_In_opt_ LPWSAPROTOCOL_INFO lpProtocolInfo,
_Out_ LPSOCKADDR lpAddress,
_Inout_ LPINT lpAddressLength
);
Run Code Online (Sandbox Code Playgroud)
AddressString一个_In_参数,而不是一个_Inout_参数.我不清楚为什么API采用非const指针,并导致编译失败,因为我有一个const char*.
我的第一个问题是,为什么WSAStringToAddress采用非常量指针?
我的第二个问题是,将常数抛弃是否安全?会WSAStringToAddress修改char*参数吗?
下面是更后面的故事的......我试图用WSAStringToAddress在inet_addr更换由于在Visual Studio中的当代版本弃用警告.
这是PetarKorponaić提供的答案问题中详述的相同问题.Korponaić遇到了同样的问题.它的额外副本的原因:
int inet_pton(int af, const char *src, void *dst)
{
struct sockaddr_storage ss;
int size = sizeof(ss);
char src_copy[INET6_ADDRSTRLEN+1];
ZeroMemory(&ss, sizeof(ss));
/* stupid non-const API */
strncpy (src_copy, src, INET6_ADDRSTRLEN+1);
src_copy[INET6_ADDRSTRLEN] = …Run Code Online (Sandbox Code Playgroud) 我们的软件(Nmap 端口扫描器)需要快速确定非阻塞 TCP 套接字的状态connect()。我们select()用来监控很多套接字,Windows 擅长在一个成功时通知我们。但是如果端口关闭并且目标发送 TCP RST,Windows 会在通知 之前继续尝试几次exceptfds,并且套接字错误WSAECONNREFUSED如预期。不过,我们的应用程序有自己的超时,并且通常会在 Windows 放弃之前将连接标记为超时。我们希望尽可能接近 Linux 的行为,即ECONNREFUSED在收到第一个 RST 后立即通知。
我们尝试使用TCP_MAXRT套接字选项,这可以立即select()向我们发出信号,但结果(对于关闭的端口)总是WSAETIMEDOUT,这使得无法区分关闭(RST)和过滤/防火墙(网络超时),这让我们回到原来的问题。确定这种区别是我们应用程序的核心功能。
那么在 Windows 上找出非阻塞套接字connect()是否已收到连接重置的最佳方法是什么?
编辑添加:这里的一个核心问题是微软关于SO_ERROR套接字选项的文档中的这一行:“这个每套接字错误代码并不总是立即设置。” 如果立即设置,我们可以在连接超时之前检查它。
我正在使用非阻塞套接字(fd_sets和select函数)编写服务器和客户端,一旦服务器关闭或关闭客户端套接字,客户端就会开始接收大量垃圾直到它崩溃.我已经被警告过,当工作时用select()插座将成为可读当连接被终止,但我怎么能知道
if( FD_ISSET( socket, &read ) )
{
}
Run Code Online (Sandbox Code Playgroud)
如果原因只是常规数据或连接已结束?
非常感谢!
我正在尝试制作一个简单的程序,它接受一个像 www.google.com 这样的字符串并返回 IP 地址......
到目前为止我所拥有的:
char* hostname = new char[www.size()+1];
std::copy(www.begin(), www.end(), hostname);
hostname[www.size()] = '\0';
struct addrinfo new_addr, *res;
getaddrinfo(www.c_str(), SERVICE.c_str(), &new_addr, &res);
cout << new_addr.ai_addr;
Run Code Online (Sandbox Code Playgroud)
第 4 个参数中的第 3 个应该做什么?getaddrinfo 函数是否修改了 new_addr 结构或什么?我不太了解 msdn 文档。解析主机名后,我想将套接字连接到它。
MSDN说:Listen() 是一个阻塞调用。我在其中使用过 listen() 的函数的代码片段如下所示:
sockaddr_in addr = {0};
int addrlen = sizeof(addr);
SOCKET sock_listen;
if(-1 == (sock_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
{
cout<<"error";
}
addr.sin_family = AF_INET;
/* Network byte ordered address for loopback */
addr.sin_addr.s_addr= inet_addr("127.0.0.1");
/* Let service provider assign a unique port from dynamic client port range */
addr.sin_port = 0;
if(-1 == bind(sock_listen, (const sockaddr *)&addr, addrlen))
{
CloseHandle((HANDLE)sock_listen_fd);
cout<<"error";
}
if(-1 == getsockname(sock_listen, (sockaddr *)&addr, &addrlen))
{
CloseHandle((HANDLE)sock_listen);
cout<<"error";
}
u_long mode = 0; …Run Code Online (Sandbox Code Playgroud) 我有以下简化的 IO 完成端口服务器 C++ 代码:
int main(..)
{
startCompletionPortThreadProc();
// Await client connection
sockaddr_in clientAddress;
int clientAddressSize = sizeof( clientAddress );
SOCKET acceptSocket = WSAAccept( serverSocket, (SOCKADDR*)&clientAddress, &clientAddressSize, NULL, NULL);
// Connected
CreateIoCompletionPort( (HANDLE)acceptSocket, completionPort, 0, 0 );
// Issue initial read
read( acceptSocket );
}
DWORD WINAPI completionPortThreadProc( LPVOID param )
{
DWORD bytesTransferred = 0;
ULONG_PTR completionKey = NULL;
LPPER_IO_DATA perIoData = NULL;
while( GetQueuedCompletionStatus( completionPort, &bytesTransferred, &completionKey, (LPOVERLAPPED*)&perIoData, INFINITE ) )
{
if( WaitForSingleObject( exitEvent, 0 ) …Run Code Online (Sandbox Code Playgroud) winsock2 ×10
sockets ×5
windows ×4
c ×3
c++ ×3
select ×2
winapi ×2
winsock ×2
blocking ×1
const ×1
getaddrinfo ×1
iocp ×1
linux ×1
networking ×1
nonblocking ×1
parameters ×1
python ×1
tcp ×1
udp ×1