这个问题类似于/sf/ask/815522991/,但我的代码与它略有不同,因此可能会导致在一个不同的答案.
我试图获得可靠的多播服务器/客户端概念验证设置.
解决方案本身是服务器/客户端连接.客户端通过TCP/IP连接到服务器.然后,服务器打开一个可靠的多播套接字供客户端监听.客户端通过TCP发送消息,服务器通过TCP回送消息IPPROTO_RM.最终目标是让许多客户端连接到服务器,所有客户端都接收每个回显的消息.
示例代码基于此页面.
我已经设置了类似的RM套接字(参见下面的清单).TCP套接字工作正常.问题在于RM套接字.服务器开启了组播插座,然后binds和connects多播地址正确.然而,客户端是listens正确的,但accept永远是对块的调用.
客户端和服务器进程都在同一主机上运行.
我已经检查过,主机上安装了多播支持(Server 2008).
更新:我注意到,如果我先从发送方侧向套接字发送一些数据,有时接受将返回.这不是理想的,也不可靠.
更新:标志指向开关.看起来像一个小集线器不会削减它.我们发生了一个搞笑的事件,导致整栋大楼失去了通讯.
short
Port = 0;
const char
*Address = "234.5.6.7";
SOCKET
RMSocket;
SOCKADDR_IN
LocalAddr,
SessionAddr;
RMSocket = socket(AF_INET, SOCK_RDM, IPPROTO_RM);
if (RMSocket == INVALID_SOCKET)
{
return Failed;
}
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_port = htons(0);
LocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if ( bind( RMSocket, (SOCKADDR*)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR )
{
return Failed;
}
SessionAddr.sin_family …Run Code Online (Sandbox Code Playgroud) MSDN 上的所有 Winsock2 示例都表明我必须将 Winsock2 库静态链接为:
#pragma comment(lib, "ws2_32.lib")
Run Code Online (Sandbox Code Playgroud)
确保构建环境链接到 Winsock 库文件 ?>Ws2_32.lib。使用 Winsock 的应用程序必须与 Ws2_32.lib >库文件链接。#pragma 注释向链接器表明需要 Ws2_32.lib > 文件。
但为什么我使用它而不是简单地加载Windows中现有的Ws2_32.dll(自Windows 2003以来,据我了解,根据MSDN https://learn.microsoft.com/en-us/windows/win32/api/winsock2/的要求nf-winsock2-recv )
所以我可以使用这样的东西:
typedef int WSAAPI(WINAPI* recv_func)(SOCKET s, char *buf, int len, int flags);
HINSTANCE hGetProcIDDLL = LoadLibraryA("ws2_32.dll");
my_recv = (recv_func)GetProcAddress(hGetProcIDDLL, "recv");
Run Code Online (Sandbox Code Playgroud)
或者我可以只使用 Winsock2.h 标头并使用 /MD 标志编译程序:
include <winsock2.h>
//#pragma comment(lib, "ws2_32.lib")
Run Code Online (Sandbox Code Playgroud)
是否可以?我可以像第一个示例一样使用 /MD 或动态加载 ws2_32.dll ,而不将 ws2_32.lib 静态链接到我的应用程序,因为自 Win2003 以来的所有 Windows 都在 System32 文件夹中包含 ws2_32.dll ?
如何增加特定套接字的TCP接收窗口? - 我知道如何通过设置注册表项TcpWindowSize来为所有套接字执行此操作,但是如何针对特定的套接字执行此操作?
根据MSFT的文件,方式是
调用Windows套接字函数setsockopt,它基于每个套接字设置接收窗口.
但是在setsockopt中,提到了SO_RCVBUF:
指定为receive保留的每个套接字缓冲区空间总数.这与SO_MAX_MSG_SIZE无关,并且不一定与TCP接收窗口的大小相对应.
那有可能吗?怎么样?
谢谢.
我在Visual Studio Pro C++中创建了一个套接字(Winsock2)来监听端口上的连接(TCP).它工作得很好,但我让它在自己的线程中运行,我希望能够关闭它,希望以后重新启动它.我可以毫无问题地终止线程,但这样做并不会阻止套接字接受新客户端(也就是说,它在我关闭线程之前就已经接受了它所做的接受).我可以将新客户连接到它但没有任何反应......它只是接受而且就是这样.我想要的是阻止它听取和接受,然后能够告诉它稍后在同一个端口再次启动.现在尝试重新启动它只是告诉我端口已经被占用.
这是listen线程函数:
DWORD WINAPI ListeningThread(void* parameter){
TCPServer *server = (TCPServer*)parameter;
try{
server = new TCPServer(listen_port);
}catch(char* err){
cout<<"ERROR: "<<err<<endl;
return -1;
}
int result = server->start_listening();
if(result < 0){
cout<<"ERROR: WSA Err # "<<WSAGetLastError()<<endl;
return result;
}
cout<<"LISTENING: "<<result<<endl<<endl;
while(true){
TCPClientProtocol *cl= new TCPClientProtocol(server->waitAndAccept());
HANDLE clientThread = CreateThread(0, 0, AcceptThread, cl, 0, 0);
cout<<"Connection spawned."<<endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以下是TCPServer中的相关功能:
TCPServer::TCPServer(int port){
listening = false;
is_bound = false;
//setup WSA
int result = WSAStartup(MAKEWORD(2, 2), (LPWSADATA) &wsaData); …Run Code Online (Sandbox Code Playgroud) 我正在尝试为C中已经与IPv4兼容的程序添加IPv6兼容性,但是在编译器方面存在一些问题.目前正在使用mingw32-gcc-4.6.2进行编译,这在使用函数inet_pton时给出了链接错误.
我试过让它为vista编译(因为inet_pton是一个vista函数),但似乎mingw缺少整个函数.
有没有办法将它添加到mingw,或者我可能错过的任何其他选项?
我在这里看到很多答案,说使用close()来销毁套接字,但是我从msdn使用的指南让我使用closesocket().我想知道是否有差异,是否有理由使用其中一个.
在这两种情况下,我都看到使用shutdown()的建议,所以这一切都很好.
我有一个用C++实现的客户端服务器体系结构,在Windows 7下使用阻塞套接字.一切都运行良好,达到一定的负载水平.如果有几个客户端(例如> 4)接收或发送兆字节数据,则有时与一个客户端的通信会冻结大约5秒钟.在这种情况下,所有其他客户端都按预期工作.
缓冲区大小为8192字节,服务器端的日志记录如下:
TimeStamp(s.ms) - 接收的字节数
...
1299514524.618 - 8192
1299514524.618 - 8192
1299514524.618 - 0004
1299514529.641 - 8192
1299514529.641 - 3744
1299514529.641 - 1460
1299514529.641 - 1460
1299514529.641 - 8192
...
似乎在5秒内只能读取4个字节.此外,我发现冻结时间总是大约5秒 - 从不4或更少,从不6或更多...
有任何想法吗?
最好的祝福
迈克尔
我在这里有这个代码来从主机名中检索IP地址:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
winsock;
function GetIPFromHost(const HostName: string): string;
type
TaPInAddr = array[0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe: PHostEnt;
pptr: PaPInAddr;
i: Integer;
begin
Result := '';
phe := GetHostByName(PChar(HostName));
if phe = nil then Exit;
pPtr := PaPInAddr(phe^.h_addr_list);
i := 0;
while pPtr^[i] <> nil do
begin
Result := inet_ntoa(pptr^[i]^);
Inc(i);
end;
end;
var
wsaData: TWSAData;
begin
if (WSAStartup($0202, wsaData) <> 0) then begin
Exit;
end;
while true do begin
sleep (1000);
GetIPFromHost …Run Code Online (Sandbox Code Playgroud) 我不能在msvc ++ 2010项目中包含WinSock2.h.起初我虽然这是我做错了,所以我创建了一个空项目来测试我的理智.空项目如下
#include <Windows.h>
#include <WinSock2.h>
int main(void){
system("echo Hello World");
system("pause");
return 0;
};
Run Code Online (Sandbox Code Playgroud)
它在没有行的情况下编译和工作正常,#include <WinSock2.h>但是当我尝试包含WinSock2.h时,它会失败并出现一长串错误.
错误:
1> Main.cpp
1>c:\program files\microsoft sdks\windows\v7.0a\include\ws2def.h(91): warning C4005: 'AF_IPX' : macro redefinition
1> c:\program files\microsoft sdks\windows\v7.0a\include\winsock.h(460) : see previous definition of 'AF_IPX'
1>c:\program files\microsoft sdks\windows\v7.0a\include\ws2def.h(131): warning C4005: 'AF_MAX' : macro redefinition
1> c:\program files\microsoft sdks\windows\v7.0a\include\winsock.h(479) : see previous definition of 'AF_MAX'
1>c:\program files\microsoft sdks\windows\v7.0a\include\ws2def.h(168): warning C4005: 'SO_DONTLINGER' : macro redefinition
1> c:\program files\microsoft sdks\windows\v7.0a\include\winsock.h(402) : see previous definition of 'SO_DONTLINGER' …Run Code Online (Sandbox Code Playgroud) 使用以下命令获取Windows-Winsock-AFD的信息级别跟踪非常容易:netsh trace start provider = Microsoft-Windows-Winsock-AFD TraceFile = my_ winsock_log3_trace.etl
生成的文件似乎不包括详细级别事件,例如"选择/投票已发布".我也尝试过:"netsh trace start provider = Microsoft-Windows-Winsock-AFD TraceFile = my_winsock_log3_trace.etl level = 5"没有帮助(同级事件)
有没有人能够以详细的方式启动winsock跟踪?
谢谢