- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我用 C++ (MinGW) 编写了一个非常简单的套接字服务器,使用这些常用函数,如
socket( PF_INET, SOCK_STREAM, 0 )...
setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &OptVal, sizeof( OptVal ) )...
bind( s, ( struct sockaddr * ) &ServerAddress, sizeof( ServerAddress ) )...
listen( s, 10 )...
多个客户端连接的处理由
select( s, &FileDescriptorClient, NULL, NULL, &tv )...
accept( Server->GetSocketHandle(), (struct sockaddr*) &ClientAddress, &Length )...
一切看起来都非常好,...直到我决定对我的服务器进行压力测试。
我的第一个测试是一个非常简单的客户端,它只做一件事:在无限循环中连接和断开连接——尽可能快。虽然这个测试非常简单,但它立即失败了。
服务器会在如此多的切换连接上阻塞,这对我来说并不奇怪,所以我在每次连接和断开连接之前在客户端中添加了一个 Sleep(5)(毫秒),一切正常。目前。
我的问题是:
目前流程如下:
如前所述:这仅在我通过 sleep 限制客户端时才有效。一旦我减少 sleep 时间,服务器就会开始跳过 pt。 4(断开连接)并储存在线下打开的连接。
我想念的重点是什么?
编辑:
编辑 2:
根据要求:源代码(削减到最小版本):
服务器的main.cpp:
#include <iostream>
#include "Server.h"
using namespace std;
int main()
{
try
{
ServerSocket srv;
while ( true )
{
srv.Open();
srv.Run();
}
}
catch( ServerException const &e )
{
std::cout << "failed to run the server" << e.what() << std::endl;
}
return 0;
}
服务器.h:
#ifndef SERVER_H
#define SERVER_H
#define SOCKETBUFLEN 10
#include <string>
#include <cstdio>
#include <vector>
#include <memory>
#include <unistd.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <sys/types.h>
class Exception : public std::exception
{
private:
std::string Message;
public:
template< typename ... Arguments >
Exception( const char * AFormat, Arguments&& ... AArguments )
{
char Buffer[ 1024 ];
sprintf( Buffer, AFormat, std::forward<Arguments>( AArguments ) ... );
Message = std::string( Buffer );
};
const char* what() const noexcept{ return Message.c_str(); }
};
class ServerException : public Exception
{
public:
template< typename ... Arguments >
ServerException( const char * AFormat, Arguments&& ... AArguments ) : Exception( AFormat, std::forward< Arguments >( AArguments ) ... ){}
};
class ClientException : public Exception
{
public:
template< typename ... Arguments >
ClientException( const char * AFormat, Arguments&& ... AArguments ) : Exception( AFormat, std::forward< Arguments >( AArguments ) ... ){}
};
class Client
{
public:
Client();
virtual ~Client();
virtual bool Authenticate( const std::string & AClientId ) = 0;
virtual bool Process( const std::string & AMessage ) = 0;
protected:
std::vector< std::string > Clients;
private:
};
class ServerSocket;
class ClientSocket;
class Socket;
class ClientSockets
{
private:
ServerSocket *OwnerServer;
fd_set FileDescriptorClient;
std::vector< ClientSocket * > Items;
std::vector< Socket * > SocketsRead;
void Append( ClientSocket * );
void OnClientConnect( SOCKET ASocketHandle, struct sockaddr_in AClientAddress );
public:
ClientSockets( ServerSocket * );
int Count( void );
void Remove( SOCKET ASocketHandle );
bool HandleConnnections( void );
void Read( void );
};
class Socket
{
protected:
SOCKET SocketHandle;
public:
Socket( SOCKET ASocketHandle = 0 ) { SocketHandle = ASocketHandle; };
SOCKET GetSocketHandle( void ) { return SocketHandle; };
virtual void Close( void ) = 0;
};
class ServerSocket : public Socket
{
public:
ServerSocket( const std::string &AHost = "127.0.0.1", const int &APort = 24442 );
virtual ~ServerSocket();
void Open( void );
void Close( void ) {};
void Run( void );
fd_set FileDescriptorServer;
private:
std::string Host;
int Port;
ClientSockets *clientSockets;
};
class ClientSocket : public Socket
{
private:
ClientSockets *FClientSockets;
public:
ClientSocket( ClientSockets *, SOCKET ASocketHandle );
virtual ~ClientSocket() {};
void Close( void );
};
#endif // SERVER_H
服务器.cpp:
#include "Server.h"
#include <cstring>
#include <cstdarg>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <thread>
#include <chrono>
#define LOG_CONNECTION_AMOUNT 100
ServerSocket::ServerSocket( const std::string &AHost, const int &APort ) :
Host( AHost ),
Port( APort ),
clientSockets( new ClientSockets( this ) ) {}
ServerSocket::~ServerSocket()
{
WSACleanup();
}
void ServerSocket::Open( void )
{
WSADATA wsa;
if ( WSAStartup( MAKEWORD( 2, 2 ), &wsa ) != 0 )
{
throw ServerException( "WSAStartup failed" );
}
if ( ( SocketHandle = socket( PF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
{
throw ServerException( "%s: unable to get a socket handle. errno: %ld", __PRETTY_FUNCTION__, errno );
}
char OptVal = 1;
if ( setsockopt( SocketHandle, SOL_SOCKET, SO_REUSEADDR, &OptVal, sizeof( OptVal ) ) == -1 )
{
throw ServerException( "%s: setsockopt failed", __PRETTY_FUNCTION__ );
}
struct sockaddr_in ServerAddress;
memset( & ServerAddress, 0x0, sizeof( ServerAddress ) );
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_addr.s_addr = inet_addr( Host.c_str() );
ServerAddress.sin_port = htons( Port );
if ( bind( SocketHandle, ( struct sockaddr * ) &ServerAddress, sizeof( ServerAddress ) ) == -1 )
{
throw ServerException( "%s: binding server address failed", __PRETTY_FUNCTION__ );
}
if ( listen( SocketHandle, 10 ) == -1 )
{
throw ServerException( "%s: listen socket failed", __PRETTY_FUNCTION__ );
}
FD_ZERO( &FileDescriptorServer );
FD_SET( SocketHandle, &FileDescriptorServer );
std::cout << "socket server fd '" << SocketHandle << "' listening on " << Host << ":" << Port << std::endl;
}
void ServerSocket::Run( void )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
do
{
try
{
if ( !clientSockets->HandleConnnections() )
{
continue;
}
clientSockets->Read();
}
catch( ServerException const &e )
{
int ErrorCode = WSAGetLastError();
std::cout << "error while server running: " << e.what() << ", code: " << ErrorCode << std::endl;
if ( ErrorCode == 10038 ) // no socket error
{
// continue; // not sure if this is the correct way to do...
}
// if ( ErrorCode == 10014 ) {} // bad address error
// if ( ErrorCode == 10054 ) {} // connection reset by peer
break;
}
catch( ... )
{
std::cout << "some exception occurred" << std::endl;
}
} while ( true );
}
ClientSockets::ClientSockets( ServerSocket * AOwnerServer )
{
OwnerServer = AOwnerServer;
}
void ClientSockets::Append( ClientSocket *AClientSocket )
{
Items.push_back( AClientSocket );
}
int ClientSockets::Count( void )
{
return Items.size();
}
bool ClientSockets::HandleConnnections( void )
{
FD_ZERO( & FileDescriptorClient );
SocketsRead.clear();
SocketsRead.push_back( OwnerServer );
for ( auto i : Items )
{
SocketsRead.push_back( i );
}
for ( auto Socket : SocketsRead )
{
if ( FD_ISSET( Socket->GetSocketHandle(), & OwnerServer->FileDescriptorServer ) )
{
FD_SET( Socket->GetSocketHandle(), & FileDescriptorClient );
}
}
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 3;
int SocketChangedCount = 0;
if ( ( SocketChangedCount = select( 0, &FileDescriptorClient, NULL, NULL, &tv ) ) == -1 )
{
throw ServerException( "%s: select failed", __PRETTY_FUNCTION__ );
}
static int scc = 0;
if ( scc != SocketChangedCount )
{
scc = SocketChangedCount;
std::cout << "socket changes: " << SocketChangedCount << std::endl;
}
if ( FD_ISSET( OwnerServer->GetSocketHandle(), &FileDescriptorClient ) )
{
struct sockaddr_in ClientAddress;
socklen_t Length = sizeof( ClientAddress );
SOCKET SocketHandle = 0;
if ( ( SocketHandle = accept( OwnerServer->GetSocketHandle(), (struct sockaddr*) &ClientAddress, &Length ) ) == INVALID_SOCKET )
{
throw ServerException( "%s: accept failed", __PRETTY_FUNCTION__ );
}
else
{
OnClientConnect( SocketHandle, ClientAddress );
}
FD_SET( SocketHandle, &OwnerServer->FileDescriptorServer );
}
return ( SocketChangedCount > 0 );
}
void ClientSockets::OnClientConnect( SOCKET ASocketHandle, struct sockaddr_in AClientAddress )
{
#if LOG_CONNECTION_AMOUNT > 0
static int ClientConnectionCounter = 0;
if ( ClientConnectionCounter++ % LOG_CONNECTION_AMOUNT == 0 )
{
std::cout << "connect fd: [" << ASocketHandle << "], serial: [" << ClientConnectionCounter << "], cnt: [" << Count() << "]" << std::endl;
}
#endif
ClientSocket *clientSocket = new ClientSocket( this, ASocketHandle );
Append( clientSocket );
}
void ClientSockets::Read( void )
{
for ( auto clientSocket : Items )
{
if ( FD_ISSET( clientSocket->GetSocketHandle(), &FileDescriptorClient ) )
{
char buf[ SOCKETBUFLEN + 1 ];
memset( buf, 0x0, sizeof( buf ) );
int BytesReceived = recv( clientSocket->GetSocketHandle(), buf, SOCKETBUFLEN, 0 );
if ( BytesReceived > 0 )
{
std::string Message = ( std::string ) buf;
if ( Message.substr( 0, 4 ) == "quit" )
{
clientSocket->Close();
break;
}
else
{
// ... do fancy stuff here...
std::cout << "read from socket: " << Message << std::endl;
}
}
else if ( BytesReceived == 0 )
{
clientSocket->Close();
break;
}
else
{
throw ServerException( "reading data failed" );
}
}
}
}
void ClientSockets::Remove( SOCKET ASocketHandle )
{
FD_CLR( ASocketHandle, & FileDescriptorClient );
std::vector< ClientSocket * >::iterator it =
Items.erase(
std::remove_if(
Items.begin(),
Items.end(),
[ ASocketHandle ]( Socket *sock ){ return sock->GetSocketHandle() == ASocketHandle; }
)
);
delete *it;
}
void ClientSocket::Close( void )
{
#if LOG_CONNECTION_AMOUNT > 0
static int ClientDisconnectionCounter = 0;
if ( ClientDisconnectionCounter++ % LOG_CONNECTION_AMOUNT == 0 )
{
std::cout << "disconnnect fd: [" << SocketHandle << "], serial: [" << ClientDisconnectionCounter << "], cnt: [" << FClientSockets->Count() << "]" << std::endl;
}
#endif
if ( closesocket( SocketHandle ) == SOCKET_ERROR )
{
throw ClientException( "closing socket failed: %ld", errno );
}
FClientSockets->Remove( SocketHandle );
}
ClientSocket::ClientSocket( ClientSockets *AClientSockets, SOCKET ASocketHandle ) :
Socket( ASocketHandle ),
FClientSockets( AClientSockets ) {}
测试客户端应用程序非常原始:我使用带有 TClientSocket 组件的 Embarcadero C++ Builder,该组件连续切换其连接状态(在非阻塞模式下)。 3 个复选框用于告诉应用程序以循环模式运行 (1)、连接前休眠 (2) 和断开连接前休眠 (3),1 个 TEdit 用于修改以毫秒为单位的休眠持续时间。
cpp文件的代码是:
#include <vcl.h>
#pragma hdrstop
#include "UnitFormMain.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
: TForm(Owner), Trigger( false ), sock( 0 )
{
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket)
{
static int ConnectionCounter = 0;
if ( ConnectionCounter++ % 100 == 0 )
{
Memo1->Lines->Add( System::Sysutils::Format( "connectionCounter '%d'", ARRAYOFCONST(( ConnectionCounter )) ) );
}
if ( CheckBoxRunLoopComponent->Checked )
{
Trigger = true;
}
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ClientSocket1Disconnect(TObject *Sender, TCustomWinSocket *Socket)
{
if ( CheckBoxRunLoopComponent->Checked )
{
Trigger = true;
}
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonToggleConnectionComponentClick(TObject *Sender)
{
ClientSocket1->Active = !ClientSocket1->Active;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::CheckBoxRunLoopComponentClick(TObject *Sender)
{
if ( dynamic_cast< TCheckBox * >( Sender )->Checked )
{
for (;;)
{
Application->ProcessMessages();
if ( !dynamic_cast< TCheckBox * >( Sender )->Checked )
{
break;
}
ToggleConnection();
}
}
}
void TFormMain::ToggleConnection( void )
{
if ( Trigger )
{
Trigger = false;
if ( ClientSocket1->Active )
{
if ( CheckBoxSleepOnDisconnect )
{
Sleep( StrToInt( Edit1->Text ) );
}
ClientSocket1->Close();
}
else
{
if ( CheckBoxSleepOnConnect->Checked )
{
Sleep( StrToInt( Edit1->Text ) );
}
ClientSocket1->Open();
}
}
}
//---------------------------------------------------------------------------
更有趣的是测试运行(服务器)的输出:
每个第 100 个切换都是协议(protocol)化的。“cnt”是 std::vector<> 中的连接数。
测试从每次切换时休眠 5 毫秒开始。在第 1500 次切换左右的某个地方,我将休眠时间减少到 1 毫秒,这导致服务器列表中的事件连接立即增加。几千个连接后 select()
失败并返回 10038
。
socket server fd '276' listening on 127.0.0.1:24442
void ServerSocket::Run()
socket changes: 1
connect fd: [280], serial: [1], cnt: [0]
disconnnect fd: [280], serial: [1], cnt: [1]
connect fd: [284], serial: [101], cnt: [0]
disconnnect fd: [284], serial: [101], cnt: [1]
connect fd: [280], serial: [201], cnt: [0]
disconnnect fd: [280], serial: [201], cnt: [1]
connect fd: [288], serial: [301], cnt: [0]
disconnnect fd: [288], serial: [301], cnt: [1]
connect fd: [292], serial: [401], cnt: [0]
disconnnect fd: [292], serial: [401], cnt: [1]
connect fd: [296], serial: [501], cnt: [0]
disconnnect fd: [296], serial: [501], cnt: [1]
connect fd: [308], serial: [601], cnt: [0]
disconnnect fd: [308], serial: [601], cnt: [1]
connect fd: [296], serial: [701], cnt: [0]
disconnnect fd: [296], serial: [701], cnt: [1]
connect fd: [296], serial: [801], cnt: [0]
disconnnect fd: [296], serial: [801], cnt: [1]
connect fd: [288], serial: [901], cnt: [0]
disconnnect fd: [288], serial: [901], cnt: [1]
connect fd: [300], serial: [1001], cnt: [0]
disconnnect fd: [300], serial: [1001], cnt: [1]
connect fd: [312], serial: [1101], cnt: [0]
disconnnect fd: [312], serial: [1101], cnt: [1]
connect fd: [300], serial: [1201], cnt: [0]
disconnnect fd: [300], serial: [1201], cnt: [1]
connect fd: [300], serial: [1301], cnt: [0]
disconnnect fd: [300], serial: [1301], cnt: [1]
connect fd: [280], serial: [1401], cnt: [0]
disconnnect fd: [280], serial: [1401], cnt: [1]
connect fd: [280], serial: [1501], cnt: [0]
disconnnect fd: [280], serial: [1501], cnt: [1]
connect fd: [316], serial: [1601], cnt: [0]
socket changes: 2
disconnnect fd: [316], serial: [1601], cnt: [2]
socket changes: 1
socket changes: 2
socket changes: 1
socket changes: 2
socket changes: 1
connect fd: [312], serial: [1701], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [312], serial: [1701], cnt: [4]
connect fd: [324], serial: [1801], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [312], serial: [1801], cnt: [4]
connect fd: [324], serial: [1901], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [324], serial: [1901], cnt: [4]
connect fd: [320], serial: [2001], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [320], serial: [2001], cnt: [4]
socket changes: 2
socket changes: 1
connect fd: [336], serial: [2101], cnt: [3]
disconnnect fd: [336], serial: [2101], cnt: [4]
connect fd: [344], serial: [2201], cnt: [3]
disconnnect fd: [344], serial: [2201], cnt: [4]
connect fd: [344], serial: [2301], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [336], serial: [2301], cnt: [4]
socket changes: 2
socket changes: 1
connect fd: [344], serial: [2401], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [336], serial: [2401], cnt: [4]
connect fd: [344], serial: [2501], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [344], serial: [2501], cnt: [4]
connect fd: [344], serial: [2601], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [344], serial: [2601], cnt: [4]
connect fd: [332], serial: [2701], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [332], serial: [2701], cnt: [4]
connect fd: [344], serial: [2801], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [332], serial: [2801], cnt: [4]
socket changes: 2
socket changes: 1
connect fd: [328], serial: [2901], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [324], serial: [2901], cnt: [4]
socket changes: 2
socket changes: 1
connect fd: [328], serial: [3001], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [324], serial: [3001], cnt: [4]
socket changes: 2
socket changes: 1
connect fd: [328], serial: [3101], cnt: [3]
socket changes: 2
socket changes: 1
disconnnect fd: [324], serial: [3101], cnt: [4]
connect fd: [324], serial: [3201], cnt: [3]
disconnnect fd: [324], serial: [3201], cnt: [4]
connect fd: [324], serial: [3301], cnt: [3]
disconnnect fd: [324], serial: [3301], cnt: [4]
socket changes: 2
socket changes: 1
error while server running: bool ClientSockets::HandleConnnections(): select failed, code: 10038
socket server fd '324' listening on 127.0.0.1:24442
void ServerSocket::Run()
socket changes: 0
在此协议(protocol)中,我还看到 select()
返回值 > 1(“套接字更改:n”),这意味着超过 1 个套接字更改了其状态。我认为这可能是指向正确解决方案的指针,但现在我不知道如何以正确的方式处理它。
编辑 3:阻塞/非阻塞:在 CPPBuilder 中,您可以使用这些设计时组件,您可以在其中设置属性:
最佳答案
我不太确定您的代码有什么问题 - 它太复杂了,我无法正确遵循,因此,我发布了一些我自己的代码可以正常工作,您可以将其用作指南。
这段代码在客户端使用 Sleep(1)
时效果很好(尽管这与您可能认为的不完全一样)。下面还有一些进一步的说明。
#define FD_SETSIZE 4096
#include <WinSock2.h> // ** before** windows.h
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#include <set>
#include <assert.h>
#pragma comment (lib, "ws2_32.lib")
const int port = 24442;
std::set <SOCKET> connected_sockets;
// main
int main (char argc, char* argv[])
{
WSADATA wsadata;
WORD version = MAKEWORD(2, 2);
int err = WSAStartup (MAKEWORD (2, 2), &wsadata);
if (err)
{
std::cout << "WSAStartup failed, error: " << err << std::endl;
return 255;
}
char buf [512];
bool is_client = argc > 1 && _stricmp (argv [1], "client") == 0;
if (is_client)
{
int lap = 0;
for ( ; ; )
{
// Client
SOCKET skt = socket (AF_INET, SOCK_STREAM, 0);
assert (skt != INVALID_SOCKET);
sockaddr_in server_address = { };
server_address.sin_family = AF_INET;
server_address.sin_port = htons (port);
inet_pton (AF_INET, "192.168.1.2", &server_address.sin_addr);
std::cout << ++lap << ": Connecting..." << std::endl;
int err = connect (skt, (const sockaddr *) &server_address, sizeof (server_address));
if (err)
{
std::cout << "connect() failed, error: " << WSAGetLastError () << std::endl;
Sleep (50);
continue;
}
memset (buf, 'Q', sizeof (buf));
std::cout << "Sending..." << std::endl;
if (send (skt, buf, sizeof (buf), 0) == SOCKET_ERROR)
std::cout << "send() failed, error: " << WSAGetLastError () << std::endl;
std::cout << "Disconnecting..." << std::endl;
closesocket (skt);
Sleep (1);
}
WSACleanup ();
return 0;
}
// Server
SOCKET listener_skt = socket (AF_INET, SOCK_STREAM, 0);
assert (listener_skt != INVALID_SOCKET);
sockaddr_in receive_address = { };
receive_address.sin_family = AF_INET;
receive_address.sin_port = htons (port);
receive_address.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (listener_skt, (const sockaddr *) &receive_address, sizeof (receive_address)) == -1)
{
std::cout << "bind failed , error: " << errno << std::endl;
return 255;
}
if (listen (listener_skt, 256) == SOCKET_ERROR)
{
std::cout << "listen() failed, error: " << WSAGetLastError () << std::endl;
return 255;
}
std::cout << "Listening..." << std::endl;
for ( ; ; )
{
fd_set read_fds;
FD_ZERO (&read_fds);
FD_SET (listener_skt, &read_fds); // listener_skt must be first
int n_fds = 0;
for (auto skt : connected_sockets)
{
FD_SET (skt, &read_fds);
if (++n_fds >= FD_SETSIZE - 1)
break;
}
n_fds = select (0, &read_fds, NULL, NULL, NULL);
if (n_fds <= 0)
{
if (n_fds < 0)
std::cout << "select failed, error: " << WSAGetLastError () << std::endl;
continue;
}
int i = 0;
if (read_fds.fd_array [i] == listener_skt)
{
SOCKET skt = accept (listener_skt, NULL, 0);
if (skt == SOCKET_ERROR)
std::cout << "accept() failed, error: " << WSAGetLastError () << std::endl;
else
{
std::cout << "Accepted connection on socket: " << skt << std::endl;
connected_sockets.insert (skt);
}
++i;
}
while (i < n_fds)
{
SOCKET skt = read_fds.fd_array [i];
int nbytes = recv (skt, buf, sizeof (buf), 0);
if (nbytes > 0)
std::cout << "Received " << nbytes << " bytes on socket " << skt << std::endl;
else
{
std::cout << "Socket " << skt << " disconnected, code: " << nbytes << std::endl;
closesocket (skt);
connected_sockets.erase (skt);
}
++i;
}
}
closesocket (listener_skt);
WSACleanup ();
return 0;
}
用法:
test_program
- 作为服务器运行
test_program client
- 作为客户端运行
注意事项:
WinSock2.h
之前,您必须#define(然后遵守)FD_SETSIZE
。您的代码不会执行此操作(= 潜在的内存覆盖,这可能是给您带来麻烦的原因之一)。listen()
的backlog
参数太小,会导致客户端在服务器繁忙时被告知无法连接(参见 here )。我选择了 256,但您选择的值应由您的用例和测试结果决定。Sleep
时间客户端。我用 Sleep(50)
尝试了 5 个客户端,它运行了 15 分钟或更长时间,没有发生任何事故。std::set
是服务器跟踪其连接的 SOCKET
的一种比 vector
更好的方法,请参阅代码。这正是 std::set
设计的目的。希望这能指明方向。如果您有任何问题,请告诉我(我喜欢编写网络代码:)。
关于C++ 套接字和压力测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51058110/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!