mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 22:00:05 +00:00
Merge pull request #966 from erwincoumans/master
add tiny clsocket cross-platform TCP library, update pybullet PDF doc
This commit is contained in:
commit
07bd911c36
@ -218,6 +218,7 @@ IF(BUILD_PYBULLET)
|
||||
|
||||
OPTION(BUILD_PYBULLET_NUMPY "Set when you want to build pybullet with NumPy support" OFF)
|
||||
OPTION(BUILD_PYBULLET_ENET "Set when you want to build pybullet with enet UDP networking support" ON)
|
||||
OPTION(BUILD_PYBULLET_CLSOCKET "Set when you want to build pybullet with enet TCP networking support" ON)
|
||||
|
||||
IF(BUILD_PYBULLET_NUMPY)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/build3/cmake)
|
||||
|
@ -71,10 +71,17 @@
|
||||
description = "Don't build Extras"
|
||||
}
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "no-clsocket",
|
||||
description = "Disable clsocket and clsocket tests (used for optional TCP networking in pybullet and shared memory C-API)"
|
||||
}
|
||||
|
||||
|
||||
newoption
|
||||
{
|
||||
trigger = "no-enet",
|
||||
description = "Disable enet and enet tests"
|
||||
description = "Disable enet and enet tests (used for optional UDP networking in pybullet and shared memory C-API)"
|
||||
}
|
||||
|
||||
newoption
|
||||
@ -251,6 +258,7 @@ end
|
||||
include "../examples/ExtendedTutorials"
|
||||
include "../examples/SharedMemory"
|
||||
include "../examples/ThirdPartyLibs/BussIK"
|
||||
|
||||
include "../examples/MultiThreading"
|
||||
|
||||
if _OPTIONS["lua"] then
|
||||
@ -270,13 +278,20 @@ end
|
||||
include "../examples/ThirdPartyLibs/midi"
|
||||
end
|
||||
|
||||
if not _OPTIONS["no-clsocket"] then
|
||||
defines {"BT_ENABLE_CLSOCKET"}
|
||||
include "../examples/ThirdPartyLibs/clsocket"
|
||||
include "../test/clsocket"
|
||||
end
|
||||
|
||||
if not _OPTIONS["no-enet"] then
|
||||
defines {"BT_ENABLE_ENET"}
|
||||
|
||||
include "../examples/ThirdPartyLibs/enet"
|
||||
include "../test/enet/nat_punchthrough/client"
|
||||
include "../test/enet/nat_punchthrough/server"
|
||||
include "../test/enet/chat/client"
|
||||
include "../test/enet/chat/server"
|
||||
defines {"BT_ENABLE_ENET"}
|
||||
end
|
||||
|
||||
if _OPTIONS["no-bullet3"] then
|
||||
|
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
SUBDIRS( HelloWorld BasicDemo )
|
||||
IF(BUILD_BULLET3)
|
||||
SUBDIRS( ExampleBrowser SharedMemory ThirdPartyLibs/Gwen ThirdPartyLibs/BussIK OpenGLWindow )
|
||||
SUBDIRS( ExampleBrowser SharedMemory ThirdPartyLibs/Gwen ThirdPartyLibs/BussIK ThirdPartyLibs/clsocket OpenGLWindow )
|
||||
ENDIF()
|
||||
IF(BUILD_PYBULLET)
|
||||
SUBDIRS(pybullet)
|
||||
|
@ -558,12 +558,18 @@ int b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle
|
||||
{
|
||||
state->m_jointPosition = status->m_sendActualStateArgs.m_actualStateQ[info.m_qIndex];
|
||||
state->m_jointVelocity = status->m_sendActualStateArgs.m_actualStateQdot[info.m_uIndex];
|
||||
for (int ii(0); ii < 6; ++ii) {
|
||||
state->m_jointForceTorque[ii] = status->m_sendActualStateArgs.m_jointReactionForces[6 * jointIndex + ii];
|
||||
}
|
||||
state->m_jointMotorTorque = status->m_sendActualStateArgs.m_jointMotorForce[jointIndex];
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
state->m_jointPosition=0;
|
||||
state->m_jointVelocity=0;
|
||||
}
|
||||
for (int ii(0); ii < 6; ++ii)
|
||||
{
|
||||
state->m_jointForceTorque[ii] = status->m_sendActualStateArgs.m_jointReactionForces[6 * jointIndex + ii];
|
||||
}
|
||||
state->m_jointMotorTorque = status->m_sendActualStateArgs.m_jointMotorForce[jointIndex];
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
255
examples/SharedMemory/PhysicsClientTCP.cpp
Normal file
255
examples/SharedMemory/PhysicsClientTCP.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
#include "PhysicsClientTCP.h"
|
||||
|
||||
#include "ActiveSocket.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../Utils/b3Clock.h"
|
||||
#include "PhysicsClient.h"
|
||||
//#include "LinearMath/btVector3.h"
|
||||
#include "SharedMemoryCommands.h"
|
||||
#include <string>
|
||||
#include "Bullet3Common/b3Logging.h"
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
|
||||
|
||||
|
||||
unsigned int b3DeserializeInt2(const unsigned char* input)
|
||||
{
|
||||
unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0];
|
||||
return tmp;
|
||||
}
|
||||
bool gVerboseNetworkMessagesClient2 = false;
|
||||
|
||||
|
||||
struct TcpNetworkedInternalData
|
||||
{
|
||||
/*
|
||||
ENetHost* m_client;
|
||||
ENetAddress m_address;
|
||||
ENetPeer* m_peer;
|
||||
ENetEvent m_event;
|
||||
*/
|
||||
CActiveSocket m_tcpSocket;
|
||||
|
||||
bool m_isConnected;
|
||||
|
||||
TcpNetworkedInternalData* m_tcpInternalData;
|
||||
|
||||
|
||||
SharedMemoryCommand m_clientCmd;
|
||||
bool m_hasCommand;
|
||||
|
||||
SharedMemoryStatus m_lastStatus;
|
||||
b3AlignedObjectArray<char> m_stream;
|
||||
|
||||
std::string m_hostName;
|
||||
int m_port;
|
||||
|
||||
b3AlignedObjectArray<unsigned char> m_tempBuffer;
|
||||
|
||||
TcpNetworkedInternalData()
|
||||
:
|
||||
m_isConnected(false),
|
||||
m_hasCommand(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool connectTCP()
|
||||
{
|
||||
if (m_isConnected)
|
||||
return true;
|
||||
|
||||
m_tcpSocket.Initialize();
|
||||
|
||||
m_isConnected = m_tcpSocket.Open(m_hostName.c_str(),m_port);
|
||||
|
||||
return m_isConnected;
|
||||
}
|
||||
|
||||
bool checkData()
|
||||
{
|
||||
bool hasStatus = false;
|
||||
|
||||
//int serviceResult = enet_host_service(m_client, &m_event, 0);
|
||||
int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE;
|
||||
|
||||
int rBytes = m_tcpSocket.Receive(maxLen);
|
||||
if (rBytes<=0)
|
||||
return false;
|
||||
|
||||
//append to tmp buffer
|
||||
//recBytes
|
||||
|
||||
unsigned char* d2 = (unsigned char*)m_tcpSocket.GetData();
|
||||
|
||||
|
||||
int curSize = m_tempBuffer.size();
|
||||
m_tempBuffer.resize(curSize+rBytes);
|
||||
for (int i=0;i<rBytes;i++)
|
||||
{
|
||||
m_tempBuffer[curSize+i] = d2[i];
|
||||
}
|
||||
|
||||
int packetSizeInBytes = -1;
|
||||
|
||||
if (m_tempBuffer.size()>=4)
|
||||
{
|
||||
packetSizeInBytes = b3DeserializeInt2(&m_tempBuffer[0]);
|
||||
}
|
||||
|
||||
if (m_tempBuffer.size() == packetSizeInBytes)
|
||||
{
|
||||
unsigned char* data = &m_tempBuffer[0];
|
||||
if (gVerboseNetworkMessagesClient2)
|
||||
{
|
||||
printf("A packet of length %d bytes received\n", m_tempBuffer.size());
|
||||
}
|
||||
|
||||
hasStatus = true;
|
||||
SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&data[4];
|
||||
if (statPtr->m_type == CMD_STEP_FORWARD_SIMULATION_COMPLETED)
|
||||
{
|
||||
SharedMemoryStatus dummy;
|
||||
dummy.m_type = CMD_STEP_FORWARD_SIMULATION_COMPLETED;
|
||||
m_lastStatus = dummy;
|
||||
m_stream.resize(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
m_lastStatus = *statPtr;
|
||||
int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus);
|
||||
int numStreamBytes = packetSizeInBytes - streamOffsetInBytes;
|
||||
m_stream.resize(numStreamBytes);
|
||||
for (int i = 0; i < numStreamBytes; i++)
|
||||
{
|
||||
m_stream[i] = data[i + streamOffsetInBytes];
|
||||
}
|
||||
}
|
||||
m_tempBuffer.clear();
|
||||
}
|
||||
return hasStatus;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
TcpNetworkedPhysicsProcessor::TcpNetworkedPhysicsProcessor(const char* hostName, int port)
|
||||
{
|
||||
m_data = new TcpNetworkedInternalData;
|
||||
if (hostName)
|
||||
{
|
||||
m_data->m_hostName = hostName;
|
||||
}
|
||||
m_data->m_port = port;
|
||||
|
||||
}
|
||||
|
||||
TcpNetworkedPhysicsProcessor::~TcpNetworkedPhysicsProcessor()
|
||||
{
|
||||
disconnect();
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
bool TcpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
|
||||
{
|
||||
if(gVerboseNetworkMessagesClient2)
|
||||
{
|
||||
printf("PhysicsClientTCP::processCommand\n");
|
||||
}
|
||||
|
||||
{
|
||||
int sz = 0;
|
||||
unsigned char* data = 0;
|
||||
m_data->m_tempBuffer.clear();
|
||||
|
||||
if (clientCmd.m_type == CMD_STEP_FORWARD_SIMULATION)
|
||||
{
|
||||
sz = sizeof(int);
|
||||
data = (unsigned char*) &clientCmd.m_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = sizeof(SharedMemoryCommand);
|
||||
data = (unsigned char*)&clientCmd;
|
||||
}
|
||||
int res;
|
||||
|
||||
m_data->m_tcpSocket.Send((const uint8 *)data,sz);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TcpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
|
||||
{
|
||||
bool hasStatus = m_data->checkData();
|
||||
|
||||
if (hasStatus)
|
||||
{
|
||||
if (gVerboseNetworkMessagesClient2)
|
||||
{
|
||||
printf("TcpNetworkedPhysicsProcessor::receiveStatus\n");
|
||||
}
|
||||
|
||||
serverStatusOut = m_data->m_lastStatus;
|
||||
int numStreamBytes = m_data->m_stream.size();
|
||||
|
||||
if (numStreamBytes < bufferSizeInBytes)
|
||||
{
|
||||
for (int i = 0; i < numStreamBytes; i++)
|
||||
{
|
||||
bufferServerToClient[i] = m_data->m_stream[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: steam buffer overflow\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return hasStatus;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TcpNetworkedPhysicsProcessor::renderScene()
|
||||
{
|
||||
}
|
||||
|
||||
void TcpNetworkedPhysicsProcessor::physicsDebugDraw(int debugDrawFlags)
|
||||
{
|
||||
}
|
||||
|
||||
void TcpNetworkedPhysicsProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper)
|
||||
{
|
||||
}
|
||||
|
||||
bool TcpNetworkedPhysicsProcessor::isConnected() const
|
||||
{
|
||||
return m_data->m_isConnected;
|
||||
}
|
||||
|
||||
|
||||
bool TcpNetworkedPhysicsProcessor::connect()
|
||||
{
|
||||
bool isConnected = m_data->connectTCP();
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
void TcpNetworkedPhysicsProcessor::disconnect()
|
||||
{
|
||||
m_data->m_tcpSocket.Close();
|
||||
m_data->m_isConnected = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
37
examples/SharedMemory/PhysicsClientTCP.h
Normal file
37
examples/SharedMemory/PhysicsClientTCP.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef PHYSICS_CLIENT_TCP_H
|
||||
#define PHYSICS_CLIENT_TCP_H
|
||||
|
||||
#include "PhysicsDirect.h"
|
||||
#include "PhysicsServerCommandProcessor.h"
|
||||
|
||||
class TcpNetworkedPhysicsProcessor : public PhysicsCommandProcessorInterface
|
||||
{
|
||||
|
||||
struct TcpNetworkedInternalData* m_data;
|
||||
|
||||
public:
|
||||
TcpNetworkedPhysicsProcessor(const char* hostName, int port);
|
||||
|
||||
virtual ~TcpNetworkedPhysicsProcessor();
|
||||
|
||||
virtual bool connect();
|
||||
|
||||
virtual void disconnect();
|
||||
|
||||
virtual bool isConnected() const;
|
||||
|
||||
virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
|
||||
|
||||
virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes);
|
||||
|
||||
virtual void renderScene();
|
||||
|
||||
virtual void physicsDebugDraw(int debugDrawFlags);
|
||||
|
||||
virtual void setGuiHelper(struct GUIHelperInterface* guiHelper);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //PHYSICS_CLIENT_TCP_H
|
||||
|
29
examples/SharedMemory/PhysicsClientTCP_C_API.cpp
Normal file
29
examples/SharedMemory/PhysicsClientTCP_C_API.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
#include "PhysicsClientTCP_C_API.h"
|
||||
#include "PhysicsClientTCP.h"
|
||||
#include "PhysicsDirect.h"
|
||||
#include <stdio.h>
|
||||
|
||||
b3PhysicsClientHandle b3ConnectPhysicsTCP(const char* hostName, int port)
|
||||
{
|
||||
|
||||
TcpNetworkedPhysicsProcessor* tcp = new TcpNetworkedPhysicsProcessor(hostName, port);
|
||||
|
||||
PhysicsDirect* direct = new PhysicsDirect(tcp, true);
|
||||
|
||||
bool connected;
|
||||
connected = direct->connect();
|
||||
if (connected)
|
||||
{
|
||||
printf("b3ConnectPhysicsTCP connected successfully.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("b3ConnectPhysicsTCP connection failed.\n");
|
||||
|
||||
}
|
||||
return (b3PhysicsClientHandle)direct;
|
||||
}
|
||||
|
||||
|
||||
|
19
examples/SharedMemory/PhysicsClientTCP_C_API.h
Normal file
19
examples/SharedMemory/PhysicsClientTCP_C_API.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef PHYSICS_CLIENT_TCP_C_API_H
|
||||
#define PHYSICS_CLIENT_TCP_C_API_H
|
||||
|
||||
#include "PhysicsClientC_API.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
///send physics commands using TCP networking
|
||||
b3PhysicsClientHandle b3ConnectPhysicsTCP(const char* hostName, int port);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //PHYSICS_CLIENT_TCP_C_API_H
|
@ -367,3 +367,5 @@ end
|
||||
|
||||
|
||||
include "udp"
|
||||
include "tcp"
|
||||
|
||||
|
265
examples/SharedMemory/tcp/main.cpp
Normal file
265
examples/SharedMemory/tcp/main.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
#include "PassiveSocket.h" // Include header for active socket object definition
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../../CommonInterfaces/CommonGUIHelperInterface.h"
|
||||
#include "Bullet3Common/b3CommandLineArgs.h"
|
||||
|
||||
#ifdef NO_SHARED_MEMORY
|
||||
#include "PhysicsServerCommandProcessor.h"
|
||||
typedef PhysicsServerCommandProcessor MyCommandProcessor;
|
||||
#else
|
||||
#include "SharedMemoryCommandProcessor.h"
|
||||
typedef SharedMemoryCommandProcessor MyCommandProcessor;
|
||||
#endif //NO_SHARED_MEMORY
|
||||
|
||||
#include "SharedMemoryCommands.h"
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
#include "PhysicsServerCommandProcessor.h"
|
||||
#include "../Utils/b3Clock.h"
|
||||
|
||||
|
||||
bool gVerboseNetworkMessagesServer = true;
|
||||
|
||||
void MySerializeInt(unsigned int sz, unsigned char* output)
|
||||
{
|
||||
unsigned int tmp = sz;
|
||||
output[0] = tmp & 255;
|
||||
tmp = tmp >> 8;
|
||||
output[1] = tmp & 255;
|
||||
tmp = tmp >> 8;
|
||||
output[2] = tmp & 255;
|
||||
tmp = tmp >> 8;
|
||||
output[3] = tmp & 255;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
b3CommandLineArgs parseArgs(argc,argv);
|
||||
b3Clock clock;
|
||||
double timeOutInSeconds = 10;
|
||||
|
||||
DummyGUIHelper guiHelper;
|
||||
MyCommandProcessor* sm = new MyCommandProcessor;
|
||||
sm->setGuiHelper(&guiHelper);
|
||||
|
||||
int port = 6667;
|
||||
if (parseArgs.GetCmdLineArgument("port",port))
|
||||
{
|
||||
printf("Using TCP port %d\n", port);
|
||||
}
|
||||
|
||||
gVerboseNetworkMessagesServer = parseArgs.CheckCmdLineFlag("verbose");
|
||||
|
||||
#ifndef NO_SHARED_MEMORY
|
||||
int key = 0;
|
||||
if (parseArgs.GetCmdLineArgument("sharedMemoryKey",key))
|
||||
{
|
||||
sm->setSharedMemoryKey(key);
|
||||
}
|
||||
#endif//NO_SHARED_MEMORY
|
||||
|
||||
bool isPhysicsClientConnected = sm->connect();
|
||||
bool exitRequested = false;
|
||||
|
||||
if (isPhysicsClientConnected)
|
||||
{
|
||||
|
||||
CPassiveSocket socket;
|
||||
CActiveSocket *pClient = NULL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize our socket object
|
||||
//--------------------------------------------------------------------------
|
||||
socket.Initialize();
|
||||
|
||||
socket.Listen("localhost", port);
|
||||
socket.SetBlocking();
|
||||
|
||||
int curNumErr = 0;
|
||||
|
||||
|
||||
while (!exitRequested)
|
||||
{
|
||||
b3Clock::usleep(0);
|
||||
|
||||
if ((pClient = socket.Accept()) != NULL)
|
||||
{
|
||||
b3AlignedObjectArray<char> bytesReceived;
|
||||
|
||||
int clientPort = socket.GetClientPort();
|
||||
printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Receive request from the client.
|
||||
//----------------------------------------------------------------------
|
||||
while (1)
|
||||
{
|
||||
//printf("try receive\n");
|
||||
bool receivedData = false;
|
||||
|
||||
int maxLen = 4 + sizeof(SharedMemoryStatus)+SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE;
|
||||
|
||||
|
||||
//heuristic to detect disconnected clients
|
||||
CSimpleSocket::CSocketError err = pClient->GetSocketError();
|
||||
if (err != CSimpleSocket::SocketSuccess)
|
||||
{
|
||||
b3Clock::usleep(100);
|
||||
|
||||
curNumErr++;
|
||||
|
||||
if (curNumErr>100)
|
||||
{
|
||||
printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pClient->Receive(maxLen))
|
||||
{
|
||||
|
||||
curNumErr = 0;
|
||||
char* msg2 = (char*) pClient->GetData();
|
||||
int numBytesRec2 = pClient->GetBytesReceived();
|
||||
|
||||
int curSize = bytesReceived.size();
|
||||
bytesReceived.resize(bytesReceived.size()+numBytesRec2);
|
||||
for (int i=0;i<numBytesRec2;i++)
|
||||
{
|
||||
bytesReceived[curSize+i] = msg2[i];
|
||||
}
|
||||
|
||||
if (bytesReceived.size() == 4 || bytesReceived.size()==sizeof(SharedMemoryCommand))
|
||||
{
|
||||
int numBytesRec = bytesReceived.size();
|
||||
|
||||
if (gVerboseNetworkMessagesServer)
|
||||
{
|
||||
printf("received message length [%d]\n",numBytesRec);
|
||||
}
|
||||
|
||||
receivedData = true;
|
||||
|
||||
if (strncmp(&bytesReceived[0],"stop",4)==0)
|
||||
{
|
||||
printf("Stop request received\n");
|
||||
exitRequested = true;
|
||||
bytesReceived.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SharedMemoryCommand cmd;
|
||||
|
||||
SharedMemoryCommand* cmdPtr = 0;
|
||||
|
||||
//performance test
|
||||
if (numBytesRec == sizeof(int))
|
||||
{
|
||||
cmdPtr = &cmd;
|
||||
cmd.m_type = *(int*)&bytesReceived[0];
|
||||
}
|
||||
|
||||
if (numBytesRec == sizeof(SharedMemoryCommand))
|
||||
{
|
||||
cmdPtr = (SharedMemoryCommand*)&bytesReceived[0];
|
||||
}
|
||||
if (cmdPtr)
|
||||
{
|
||||
SharedMemoryStatus serverStatus;
|
||||
b3AlignedObjectArray<char> buffer;
|
||||
buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE);
|
||||
|
||||
bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size());
|
||||
|
||||
double startTimeSeconds = clock.getTimeInSeconds();
|
||||
double curTimeSeconds = clock.getTimeInSeconds();
|
||||
|
||||
while ((!hasStatus) && ((curTimeSeconds - startTimeSeconds) <timeOutInSeconds))
|
||||
{
|
||||
hasStatus = sm->receiveStatus(serverStatus, &buffer[0], buffer.size());
|
||||
curTimeSeconds = clock.getTimeInSeconds();
|
||||
}
|
||||
if (gVerboseNetworkMessagesServer)
|
||||
{
|
||||
printf("buffer.size = %d\n", buffer.size());
|
||||
printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes);
|
||||
}
|
||||
if (hasStatus)
|
||||
{
|
||||
b3AlignedObjectArray<unsigned char> packetData;
|
||||
unsigned char* statBytes = (unsigned char*)&serverStatus;
|
||||
|
||||
if (cmdPtr->m_type == CMD_STEP_FORWARD_SIMULATION)
|
||||
{
|
||||
packetData.resize(4 + sizeof(int));
|
||||
int sz = packetData.size();
|
||||
int curPos = 0;
|
||||
|
||||
MySerializeInt(sz, &packetData[curPos]);
|
||||
curPos += 4;
|
||||
for (int i = 0; i < sizeof(int); i++)
|
||||
{
|
||||
packetData[i + curPos] = statBytes[i];
|
||||
}
|
||||
curPos += sizeof(int);
|
||||
|
||||
pClient->Send( &packetData[0], packetData.size() );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//create packetData with [int packetSizeInBytes, status, streamBytes)
|
||||
packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes);
|
||||
int sz = packetData.size();
|
||||
int curPos = 0;
|
||||
|
||||
MySerializeInt(sz, &packetData[curPos]);
|
||||
curPos += 4;
|
||||
for (int i = 0; i < sizeof(SharedMemoryStatus); i++)
|
||||
{
|
||||
packetData[i + curPos] = statBytes[i];
|
||||
}
|
||||
curPos += sizeof(SharedMemoryStatus);
|
||||
|
||||
for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++)
|
||||
{
|
||||
packetData[i + curPos] = buffer[i];
|
||||
}
|
||||
|
||||
pClient->Send( &packetData[0], packetData.size() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("received packet with unknown contents\n");
|
||||
}
|
||||
bytesReceived.clear();
|
||||
|
||||
}
|
||||
}
|
||||
if (!receivedData)
|
||||
{
|
||||
//printf("Didn't receive data.\n");
|
||||
}
|
||||
}
|
||||
printf("Disconnecting client.\n");
|
||||
pClient->Close();
|
||||
delete pClient;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
socket.Close();
|
||||
socket.Shutdown(CSimpleSocket::Both);
|
||||
}
|
||||
|
||||
delete sm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
141
examples/SharedMemory/tcp/premake4.lua
Normal file
141
examples/SharedMemory/tcp/premake4.lua
Normal file
@ -0,0 +1,141 @@
|
||||
|
||||
project ("App_PhysicsServerSharedMemoryBridgeTCP")
|
||||
|
||||
language "C++"
|
||||
|
||||
kind "ConsoleApp"
|
||||
|
||||
includedirs {"../../ThirdPartyLibs/clsocket/src","../../../src",".."}
|
||||
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
|
||||
links {
|
||||
"clsocket",
|
||||
"BulletFileLoader",
|
||||
"Bullet3Common",
|
||||
"LinearMath"
|
||||
}
|
||||
|
||||
files {
|
||||
"main.cpp",
|
||||
"../PhysicsClient.cpp",
|
||||
"../PhysicsClient.h",
|
||||
"../PhysicsDirect.cpp",
|
||||
"../PhysicsDirect.h",
|
||||
"../PhysicsCommandProcessorInterface.h",
|
||||
"../SharedMemoryCommandProcessor.cpp",
|
||||
"../SharedMemoryCommandProcessor.h",
|
||||
"../PhysicsClientC_API.cpp",
|
||||
"../PhysicsClientC_API.h",
|
||||
"../Win32SharedMemory.cpp",
|
||||
"../Win32SharedMemory.h",
|
||||
"../PosixSharedMemory.cpp",
|
||||
"../PosixSharedMemory.h",
|
||||
"../../Utils/b3ResourcePath.cpp",
|
||||
"../../Utils/b3ResourcePath.h",
|
||||
"../../Utils/b3Clock.cpp",
|
||||
"../../Utils/b3Clock.h",
|
||||
}
|
||||
|
||||
|
||||
project "App_PhysicsServerTCP"
|
||||
|
||||
if _OPTIONS["ios"] then
|
||||
kind "WindowedApp"
|
||||
else
|
||||
kind "ConsoleApp"
|
||||
end
|
||||
|
||||
defines { "NO_SHARED_MEMORY" }
|
||||
|
||||
includedirs {"..","../../../src", "../../ThirdPartyLibs","../../ThirdPartyLibs/clsocket/src"}
|
||||
|
||||
links {
|
||||
"clsocket","Bullet3Common","BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision", "LinearMath", "BussIK"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
language "C++"
|
||||
|
||||
myfiles =
|
||||
{
|
||||
"../IKTrajectoryHelper.cpp",
|
||||
"../IKTrajectoryHelper.h",
|
||||
"../SharedMemoryCommands.h",
|
||||
"../SharedMemoryPublic.h",
|
||||
"../PhysicsServerCommandProcessor.cpp",
|
||||
"../PhysicsServerCommandProcessor.h",
|
||||
"../TinyRendererVisualShapeConverter.cpp",
|
||||
"../TinyRendererVisualShapeConverter.h",
|
||||
"../../TinyRenderer/geometry.cpp",
|
||||
"../../TinyRenderer/model.cpp",
|
||||
"../../TinyRenderer/tgaimage.cpp",
|
||||
"../../TinyRenderer/our_gl.cpp",
|
||||
"../../TinyRenderer/TinyRenderer.cpp",
|
||||
"../../OpenGLWindow/SimpleCamera.cpp",
|
||||
"../../OpenGLWindow/SimpleCamera.h",
|
||||
"../../Importers/ImportURDFDemo/ConvertRigidBodies2MultiBody.h",
|
||||
"../../Importers/ImportURDFDemo/MultiBodyCreationInterface.h",
|
||||
"../../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
|
||||
"../../Importers/ImportURDFDemo/MyMultiBodyCreator.h",
|
||||
"../../Importers/ImportMJCFDemo/BulletMJCFImporter.cpp",
|
||||
"../../Importers/ImportMJCFDemo/BulletMJCFImporter.h",
|
||||
"../../Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
|
||||
"../../Importers/ImportURDFDemo/BulletUrdfImporter.h",
|
||||
"../../Importers/ImportURDFDemo/UrdfParser.cpp",
|
||||
"../../Importers/ImportURDFDemo/urdfStringSplit.cpp",
|
||||
"../../Importers/ImportURDFDemo/UrdfParser.cpp",
|
||||
"../../Importers/ImportURDFDemo/UrdfParser.h",
|
||||
"../../Importers/ImportURDFDemo/URDF2Bullet.cpp",
|
||||
"../../Importers/ImportURDFDemo/URDF2Bullet.h",
|
||||
"../../Utils/b3ResourcePath.cpp",
|
||||
"../../Utils/b3Clock.cpp",
|
||||
"../../Utils/RobotLoggingUtil.cpp",
|
||||
"../../Utils/RobotLoggingUtil.h",
|
||||
"../../../Extras/Serialize/BulletWorldImporter/*",
|
||||
"../../../Extras/Serialize/BulletFileLoader/*",
|
||||
"../../Importers/ImportURDFDemo/URDFImporterInterface.h",
|
||||
"../../Importers/ImportURDFDemo/URDFJointTypes.h",
|
||||
"../../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
|
||||
"../../Importers/ImportObjDemo/LoadMeshFromObj.cpp",
|
||||
"../../Importers/ImportSTLDemo/ImportSTLSetup.h",
|
||||
"../../Importers/ImportSTLDemo/LoadMeshFromSTL.h",
|
||||
"../../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
|
||||
"../../Importers/ImportColladaDemo/ColladaGraphicsInstance.h",
|
||||
"../../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
|
||||
"../../ThirdPartyLibs/tinyxml/tinystr.cpp",
|
||||
"../../ThirdPartyLibs/tinyxml/tinyxml.cpp",
|
||||
"../../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
|
||||
"../../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
|
||||
"../../Importers/ImportMeshUtility/b3ImportMeshUtility.cpp",
|
||||
"../../ThirdPartyLibs/stb_image/stb_image.cpp",
|
||||
}
|
||||
|
||||
files {
|
||||
myfiles,
|
||||
"main.cpp",
|
||||
}
|
||||
|
@ -133,9 +133,11 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (gVerboseNetworkMessagesServer)
|
||||
{
|
||||
int dataLen = (int)event.packet->dataLength;
|
||||
|
||||
printf("A packet of length %u containing '%s' was "
|
||||
"received from %s on channel %u.\n",
|
||||
event.packet->dataLength,
|
||||
dataLen,
|
||||
event.packet->data,
|
||||
event.peer->data,
|
||||
event.channelID);
|
||||
|
81
examples/ThirdPartyLibs/clsocket/CMakeLists.txt
Normal file
81
examples/ThirdPartyLibs/clsocket/CMakeLists.txt
Normal file
@ -0,0 +1,81 @@
|
||||
#cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
#project(clsocket)
|
||||
|
||||
# set up versioning.
|
||||
#set(BUILD_MAJOR "1")
|
||||
#set(BUILD_MINOR "4")
|
||||
#set(BUILD_VERSION "3")
|
||||
|
||||
include_directories(src)
|
||||
|
||||
SET(CLSOCKET_HEADERS
|
||||
src/ActiveSocket.h
|
||||
src/Host.h
|
||||
src/PassiveSocket.h
|
||||
src/SimpleSocket.h
|
||||
src/StatTimer.h
|
||||
)
|
||||
|
||||
SET(CLSOCKET_SOURCES
|
||||
src/SimpleSocket.cpp
|
||||
src/ActiveSocket.cpp
|
||||
src/PassiveSocket.cpp
|
||||
)
|
||||
|
||||
# mark headers as headers...
|
||||
SET_SOURCE_FILES_PROPERTIES( ${CLSOCKET_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE )
|
||||
# append to sources so that dependency checks work on headers
|
||||
LIST(APPEND CLSOCKET_SOURCES ${CLSOCKET_HEADERS})
|
||||
|
||||
# OS and compiler checks.
|
||||
if(UNIX)
|
||||
# linux / normal unix
|
||||
add_definitions(-D_LINUX)
|
||||
if(CYGWIN)
|
||||
# Special Cygwin stuff here
|
||||
elseif(APPLE)
|
||||
# Special Apple stuff here
|
||||
remove_definitions(-D_LINUX)
|
||||
add_definitions(-D_DARWIN)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
SET(PROJECT_LIBS Ws2_32.lib)
|
||||
if(MINGW)
|
||||
# Special MINGW stuff here
|
||||
elseif(MSVC)
|
||||
# Special MSVC stuff here
|
||||
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||
else()
|
||||
# No idea what it is, but there's a good chance it's too weird.
|
||||
MESSAGE( FATAL_ERROR "Using unknown WIN32 compiler... NOT. Please add to build system." )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
OPTION(CLSOCKET_SHARED "Build clsocket lib as shared." OFF)
|
||||
OPTION(CLSOCKET_DEP_ONLY "Build for use inside other CMake projects as dependency." OFF)
|
||||
|
||||
# make the lib
|
||||
if(CLSOCKET_SHARED)
|
||||
if(CLSOCKET_DEP_ONLY)
|
||||
ADD_LIBRARY(clsocket SHARED EXCLUDE_FROM_ALL ${CLSOCKET_SOURCES})
|
||||
else()
|
||||
ADD_LIBRARY(clsocket SHARED ${CLSOCKET_SOURCES})
|
||||
endif()
|
||||
else()
|
||||
if(CLSOCKET_DEP_ONLY)
|
||||
ADD_LIBRARY(clsocket STATIC EXCLUDE_FROM_ALL ${CLSOCKET_SOURCES})
|
||||
else()
|
||||
ADD_LIBRARY(clsocket STATIC ${CLSOCKET_SOURCES})
|
||||
endif()
|
||||
endif()
|
||||
TARGET_LINK_LIBRARIES(clsocket ${PROJECT_LIBS})
|
||||
|
||||
# install into configured prefix
|
||||
if(NOT CLSOCKET_DEP_ONLY)
|
||||
install(TARGETS clsocket ARCHIVE DESTINATION lib LIBRARY DESTINATION lib)
|
||||
install(FILES ${CLSOCKET_HEADERS} DESTINATION include)
|
||||
else()
|
||||
|
||||
endif()
|
||||
|
143
examples/ThirdPartyLibs/clsocket/README
Normal file
143
examples/ThirdPartyLibs/clsocket/README
Normal file
@ -0,0 +1,143 @@
|
||||
Fork from https://github.com/DFHack/clsocket to be used in Bullet Physics SDK
|
||||
Modifications: custom build system (CMake, premake etc), use preprocessor define _WIN32 instead of WIN32, __LINUX__, __APPLE__
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
* History
|
||||
------------------------------------------------------------------------------------------
|
||||
Written by Mark Carrier to provide a mechanism for writing cross platform socket code. This library was originally written to only support blocking TCP sockets. Over the years it has been extended to support UDP and RAW sockets as well. This is the first official release of the library and the following functionality is supported:
|
||||
|
||||
* Cross platform socket support.
|
||||
o Windows 95, Windows 98, Windows XP
|
||||
o Linux, Unix
|
||||
o Macintosh OSX
|
||||
* Support for sychronious, and asychronious sockets
|
||||
* Supports TCP Streams
|
||||
* Supports UDP Datagrams
|
||||
* Supports Raw Sockets
|
||||
* Thread Safe
|
||||
* Signal Safe
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
* SimpleSocket Class Overview
|
||||
------------------------------------------------------------------------------------------
|
||||
Network communications via sockets can be abstracted into two categories of functionality; the active socket and the passive socket. The active socket object initiates a connection with a known host, whereas the passive socket object waits (or listens) for inbound requests for communication. The functionality of both objects is identical as far as sending and receiving data. This library makes distinction between the two objects because the operations for constructing and destructing the two are different.
|
||||
|
||||
This library is different from other socket libraries which define TCP sockets, UDP sockets, HTTP sockets, etc. The reason is the operations required for TCP, UDP, and RAW network communication is identical from a logical stand point. Thus a program could initially be written employing TCP streams, and then at some future point it could be discovered that UDP datagrams would satisify the solution. Changing between the two transport protocols would only require changing how the object is instantiated. The remaining code would in theory require minimal to no changes.
|
||||
|
||||
This library avoids abstractions like HTTP socket, or SMTP socket, soley because this type of object mixes the application and the transport layer. These types of abstractions can be created using this library as a base class.
|
||||
|
||||
The simple socket library is comprised of two class which can be used to represent all socket communications.
|
||||
|
||||
* Active Socket Class
|
||||
* Passive Socket Class
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
* SimpleSocket Class Examples
|
||||
------------------------------------------------------------------------------------------
|
||||
When operating on a socket object most methods will return true or false
|
||||
Simple Active Socket
|
||||
As mentioned previously the active socket (CActiveSocket) is used to initiate a connections with a server on some known port. So you want to connect to an existing server...
|
||||
|
||||
How do you do it?
|
||||
|
||||
There are many ways using the existing Berkley Socket API, but the goal of this class is to remove the many calls and man page lookups and replace them with clear, concise set of methods which allow a developer to focus on the logic of network programming.
|
||||
|
||||
The following code will connect to a DAYTIME server on port 13, query for the current time, and close the socket.
|
||||
|
||||
#include <string.h>
|
||||
#include "ActiveSocket.h" // Include header for active socket object definition
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CActiveSocket socket; // Instantiate active socket object (defaults to TCP).
|
||||
char time[50];
|
||||
|
||||
memset(&time, 0, 50);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize our socket object
|
||||
//--------------------------------------------------------------------------
|
||||
socket.Initialize();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create a connection to the time server so that data can be sent
|
||||
// and received.
|
||||
//--------------------------------------------------------------------------
|
||||
if (socket.Open("time-C.timefreq.bldrdoc.gov", 13))
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Send a requtest the server requesting the current time.
|
||||
//----------------------------------------------------------------------
|
||||
if (socket.Send((const uint8 *)"\n", 1))
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Receive response from the server.
|
||||
//----------------------------------------------------------------------
|
||||
socket.Receive(49);
|
||||
memcpy(&time, socket.GetData(), 49);
|
||||
printf("%s\n", time);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Close the connection.
|
||||
//----------------------------------------------------------------------
|
||||
socket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
You can see that the amount of code required to an object for network communciation is very small and simple.
|
||||
Simple Passive Socket
|
||||
Now you want to build a server.
|
||||
|
||||
How do you do it?
|
||||
|
||||
For a practical test lets build an echo server. The server will listen on port 6789 an repsond back with what ever has been sent to the server.
|
||||
|
||||
#include "PassiveSocket.h" // Include header for active socket object definition
|
||||
|
||||
#define MAX_PACKET 4096
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CPassiveSocket socket;
|
||||
CActiveSocket *pClient = NULL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize our socket object
|
||||
//--------------------------------------------------------------------------
|
||||
socket.Initialize();
|
||||
|
||||
socket.Listen("127.0.0.1", 6789);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((pClient = socket.Accept()) != NULL)
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Receive request from the client.
|
||||
//----------------------------------------------------------------------
|
||||
if (pClient->Receive(MAX_PACKET))
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
// Send response to client and close connection to the client.
|
||||
//------------------------------------------------------------------
|
||||
pClient->Send( pClient->GetData(), pClient->GetBytesReceived() );
|
||||
pClient->Close();
|
||||
}
|
||||
|
||||
delete pClient;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Receive request from the client.
|
||||
//-----------------------------------------------------------------------------
|
||||
socket.Close();
|
||||
|
||||
return 1;
|
||||
}
|
479
examples/ThirdPartyLibs/clsocket/ReleaseNotes
Normal file
479
examples/ThirdPartyLibs/clsocket/ReleaseNotes
Normal file
@ -0,0 +1,479 @@
|
||||
===============================================================================
|
||||
Release v1.4.1
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* New methods:
|
||||
CSimpleSocket::EnableNagleAlgorithm()
|
||||
CSimpleSocket::DisableNagleAlgorithm()
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#95 - Add support to enable/disable Nable algorithm
|
||||
#131 - Multicast receiver not working
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.4.0
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* Support for multicast
|
||||
* New methods:
|
||||
CPassiveSocket::BindMulticast()
|
||||
CSimpleSocket::SetMulticast()
|
||||
CSimpleSocket::GetMulticast()
|
||||
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#92 - Add multicast to library
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.3.3
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* Now compiles for Macintosh - DMG file not yet supported
|
||||
* New method CSimpleSocket::Shutdown() - used to control
|
||||
shutdown on socket.
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#49 - Support for Macintosh
|
||||
#86 - Create new method to control shutdown of socket
|
||||
#87 - Memory leak detected
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.3.2
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#84 - CActiveSocket::Close() shutsdown both sides of the socket
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#49 - Support for Macintosh.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.3.1
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* New methods:
|
||||
SetOptionLinger() - Enable/disable linger option.
|
||||
SetOptionReuseAddr() - Set option reuse port.
|
||||
* SimpleSocket::Receive() will only allocate a buffer if the internal buffer
|
||||
is NULL or the buffer size is not equal to the previously allocated
|
||||
buffer.
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#64 - Method GetClientPort() returns value in byte swapped order
|
||||
#83 - WIN32 SetBlocking() is broke.
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#49 - Support for Macintosh.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.3.0
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* New methods:
|
||||
SendVector() - implements the iovec functionality on both linux and
|
||||
Windows.
|
||||
SetSendWindowSize() - Sent the TCP window size for send.
|
||||
SetReceiveWindowSize() - Set the TCP windows size for receive.
|
||||
GetSendWindowSize() - Get the TCP window size for send.
|
||||
GetReceiveWindowSize() - Get the TCP window size fo receive.
|
||||
Select(int sec, int usec) - Overloaded function to specify timeout
|
||||
value of select.
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#33 - Add SendVector mehtod to class
|
||||
#41 - Sockets library MUST be signal safe
|
||||
#51 - Add support to set TCP windows size
|
||||
#52 - Select closes socket if timeout occurs
|
||||
#53 - UDP receive always fails even when successful
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags.
|
||||
#48 - Finish support for RAW sockets.
|
||||
#49 - Support for Macintosh.
|
||||
#50 - Add IPV6 support
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.2.0
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* New method SetSocketDscp() and GetSocketDscp() for setting and getting DSCP values.
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#17 - Finish documentation of library
|
||||
#34 - Add SendFile() method to class
|
||||
#37 - Make new methods GetServerAddress() and GetClientAddress()
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
#41 - Sockets library MUST be signal safe
|
||||
#44 - Add MTU size test to unit test so fragmentation can be tested.
|
||||
#45 - Test Select() with Recv() and Send() set as non-blocking.
|
||||
#47 - Mechanism to setting/setting socket options/flags
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.1.0
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* UDP Now supported
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
* SetSocketExpedited() method.
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#18 - Compile under windows
|
||||
#24 - Add more type and error checking to CSocket
|
||||
#29 - Add UDP support
|
||||
#35 - unit testing of socket library causes crash on windows
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.0.3
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* New method SetSocketExpedited() for setting expedited traffice (DSCP settings).
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
#27 - Finish adding stats code to CSocket class.
|
||||
#30 - ConnectTCP() does not return correct error for inavlid IP Address.
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Release v1.0.2
|
||||
===============================================================================
|
||||
|
||||
I. New Features
|
||||
---------------
|
||||
* Implemented a new socket mode "CSocketMode::Passive" which allows the creation
|
||||
of a listening socket. Two new methods are available to control behavior for
|
||||
the listening socket: Listen() and Accept().
|
||||
|
||||
II. Deprecated Functionality
|
||||
----------------------------
|
||||
|
||||
III. Bug Fixes
|
||||
--------------
|
||||
#23 - Create Listen() method
|
||||
|
||||
Reported Bugs
|
||||
-------------
|
||||
|
||||
Unreported Bugs
|
||||
---------------
|
||||
|
||||
IV. Known Issues
|
||||
----------------
|
||||
|
||||
V. Configuration Changes
|
||||
------------------------
|
||||
|
||||
VI. Release Tag Dependencies
|
||||
----------------------------
|
||||
|
||||
VII. Errata
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
-------------
|
||||
|
||||
VIII. Documentation Changes
|
||||
----------------------------
|
24
examples/ThirdPartyLibs/clsocket/premake4.lua
Normal file
24
examples/ThirdPartyLibs/clsocket/premake4.lua
Normal file
@ -0,0 +1,24 @@
|
||||
project "clsocket"
|
||||
|
||||
kind "StaticLib"
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32","_WINSOCK_DEPRECATED_NO_WARNINGS" }
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"HAS_SOCKLEN_T","_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"HAS_SOCKLEN_T","_DARWIN"}
|
||||
end
|
||||
|
||||
|
||||
includedirs {
|
||||
".","include","src"
|
||||
}
|
||||
files {
|
||||
"src/SimpleSocket.cpp",
|
||||
"src/ActiveSocket.cpp",
|
||||
"src/PassiveSocket.cpp",
|
||||
"**.h"
|
||||
}
|
310
examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp
Normal file
310
examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* CActiveSocket.cpp - Active Socket Implementation */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "ActiveSocket.h"
|
||||
|
||||
CActiveSocket::CActiveSocket(CSocketType nType) : CSimpleSocket(nType)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectTCP() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectTCP(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Preconnection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) ==
|
||||
CSimpleSocket::SocketError)
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
// Get error value this might be a non-blocking socket so we
|
||||
// must first check.
|
||||
//--------------------------------------------------------------
|
||||
TranslateSocketError();
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// If the socket is non-blocking and the current socket error
|
||||
// is SocketEinprogress or SocketEwouldblock then poll connection
|
||||
// with select for designated timeout period.
|
||||
// Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.
|
||||
//--------------------------------------------------------------
|
||||
if ((IsNonblocking()) &&
|
||||
((GetSocketError() == CSimpleSocket::SocketEwouldblock) ||
|
||||
(GetSocketError() == CSimpleSocket::SocketEinprogress)))
|
||||
{
|
||||
bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateSocketError();
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectUDP() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Pre-connection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
TranslateSocketError();
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectRAW() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectRAW(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
//------------------------------------------------------------------
|
||||
// Pre-connection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
TranslateSocketError();
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Open() - Create a connection to a specified address on a specified port
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::Open(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
|
||||
if (IsSocketValid() == false)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidSocket);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
if (pAddr == NULL)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidAddress);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
if (nPort == 0)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidPort);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
switch (m_nSocketType)
|
||||
{
|
||||
case CSimpleSocket::SocketTypeTcp :
|
||||
{
|
||||
bRetVal = ConnectTCP(pAddr, nPort);
|
||||
break;
|
||||
}
|
||||
case CSimpleSocket::SocketTypeUdp :
|
||||
{
|
||||
bRetVal = ConnectUDP(pAddr, nPort);
|
||||
break;
|
||||
}
|
||||
case CSimpleSocket::SocketTypeRaw :
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If successful then create a local copy of the address and port
|
||||
//--------------------------------------------------------------------------
|
||||
if (bRetVal)
|
||||
{
|
||||
socklen_t nSockLen = sizeof(struct sockaddr);
|
||||
|
||||
memset(&m_stServerSockaddr, 0, nSockLen);
|
||||
getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen);
|
||||
|
||||
nSockLen = sizeof(struct sockaddr);
|
||||
memset(&m_stClientSockaddr, 0, nSockLen);
|
||||
getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen);
|
||||
|
||||
SetSocketError(SocketSuccess);
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
91
examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h
Normal file
91
examples/ThirdPartyLibs/clsocket/src/ActiveSocket.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* ActiveSocket.h - Active Socket Decleration */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifndef __ACTIVESOCKET_H__
|
||||
#define __ACTIVESOCKET_H__
|
||||
|
||||
#include "SimpleSocket.h"
|
||||
|
||||
class CPassiveSocket;
|
||||
|
||||
/// Provides a platform independent class to create an active socket.
|
||||
/// An active socket is used to create a socket which connects to a server.
|
||||
/// This type of object would be used when an application needs to send/receive
|
||||
/// data from a server.
|
||||
class CActiveSocket : public CSimpleSocket {
|
||||
public:
|
||||
friend class CPassiveSocket;
|
||||
|
||||
CActiveSocket(CSocketType type = SocketTypeTcp);
|
||||
virtual ~CActiveSocket() {
|
||||
Close();
|
||||
};
|
||||
|
||||
/// Established a connection to the address specified by pAddr.
|
||||
/// Connection-based protocol sockets (CSocket::SocketTypeTcp) may
|
||||
/// successfully call Open() only once, however; connectionless protocol
|
||||
/// sockets (CSocket::SocketTypeUdp) may use Open() multiple times to
|
||||
/// change their association.
|
||||
/// @param pAddr specifies the destination address to connect.
|
||||
/// @param nPort specifies the destination port.
|
||||
/// @return true if successful connection made, otherwise false.
|
||||
virtual bool Open(const char *pAddr, uint16 nPort);
|
||||
|
||||
private:
|
||||
/// Utility function used to create a TCP connection, called from Open().
|
||||
/// @return true if successful connection made, otherwise false.
|
||||
bool ConnectTCP(const char *pAddr, uint16 nPort);
|
||||
|
||||
/// Utility function used to create a UDP connection, called from Open().
|
||||
/// @return true if successful connection made, otherwise false.
|
||||
bool ConnectUDP(const char *pAddr, uint16 nPort);
|
||||
|
||||
/// Utility function used to create a RAW connection, called from Open().
|
||||
/// @return true if successful connection made, otherwise false.
|
||||
bool ConnectRAW(const char *pAddr, uint16 nPort);
|
||||
|
||||
private:
|
||||
struct hostent *m_pHE;
|
||||
};
|
||||
|
||||
#endif /* __ACTIVESOCKET_H__ */
|
||||
|
257
examples/ThirdPartyLibs/clsocket/src/Host.h
Normal file
257
examples/ThirdPartyLibs/clsocket/src/Host.h
Normal file
@ -0,0 +1,257 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Host.h - Basic header file to provide cross-platform solutions via */
|
||||
/* macros, conditional compilation, etc. */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifndef __HOST_H__
|
||||
#define __HOST_H__
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Type Definition Macros */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef __WORDSIZE
|
||||
/* Assume 32 */
|
||||
#define __WORDSIZE 32
|
||||
#endif
|
||||
|
||||
#if defined(_LINUX) || defined(_DARWIN)
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
typedef unsigned long long int uint64;
|
||||
typedef long long int int64;
|
||||
#elif (__WORDSIZE == 32)
|
||||
__extension__
|
||||
typedef long long int int64;
|
||||
__extension__
|
||||
typedef unsigned long long int uint64;
|
||||
#elif (__WORDSIZE == 64)
|
||||
typedef unsigned long int uint64;
|
||||
typedef long int int64;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (UCHAR_MAX)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (USHRT_MAX)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (ULONG_MAX)
|
||||
#endif
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
#define SIZE_MAX (18446744073709551615UL)
|
||||
#else
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX (4294967295U)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#define ssize_t size_t
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef htonll
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define htonll(x) (x)
|
||||
#define ntohll(x) (x)
|
||||
#else
|
||||
#define htonll(x) ((((uint64)htonl(x)) << 32) + htonl(x >> 32))
|
||||
#define ntohll(x) ((((uint64)ntohl(x)) << 32) + ntohl(x >> 32))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Socket Macros */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef WIN32
|
||||
#define SHUT_RD 0
|
||||
#define SHUT_WR 1
|
||||
#define SHUT_RDWR 2
|
||||
#define ACCEPT(a,b,c) accept(a,b,c)
|
||||
#define CONNECT(a,b,c) connect(a,b,c)
|
||||
#define CLOSE(a) closesocket(a)
|
||||
#define READ(a,b,c) read(a,b,c)
|
||||
#define RECV(a,b,c,d) recv(a, (char *)b, c, d)
|
||||
#define RECVFROM(a,b,c,d,e,f) recvfrom(a, (char *)b, c, d, (sockaddr *)e, (int *)f)
|
||||
#define RECV_FLAGS MSG_WAITALL
|
||||
#define SELECT(a,b,c,d,e) select((int32)a,b,c,d,e)
|
||||
#define SEND(a,b,c,d) send(a, (const char *)b, (int)c, d)
|
||||
#define SENDTO(a,b,c,d,e,f) sendto(a, (const char *)b, (int)c, d, e, f)
|
||||
#define SEND_FLAGS 0
|
||||
#define SENDFILE(a,b,c,d) sendfile(a, b, c, d)
|
||||
#define SET_SOCKET_ERROR(x,y) errno=y
|
||||
#define SOCKET_ERROR_INTERUPT EINTR
|
||||
#define SOCKET_ERROR_TIMEDOUT EAGAIN
|
||||
#define WRITE(a,b,c) write(a,b,c)
|
||||
#define WRITEV(a,b,c) Writev(b, c)
|
||||
#define GETSOCKOPT(a,b,c,d,e) getsockopt(a,b,c,(char *)d, (int *)e)
|
||||
#define SETSOCKOPT(a,b,c,d,e) setsockopt(a,b,c,(char *)d, (int)e)
|
||||
#define GETHOSTBYNAME(a) gethostbyname(a)
|
||||
#endif
|
||||
|
||||
#if defined(_LINUX) || defined(_DARWIN)
|
||||
#define ACCEPT(a,b,c) accept(a,b,c)
|
||||
#define CONNECT(a,b,c) connect(a,b,c)
|
||||
#define CLOSE(a) close(a)
|
||||
#define READ(a,b,c) read(a,b,c)
|
||||
#define RECV(a,b,c,d) recv(a, (void *)b, c, d)
|
||||
#define RECVFROM(a,b,c,d,e,f) recvfrom(a, (char *)b, c, d, (sockaddr *)e, f)
|
||||
#define RECV_FLAGS MSG_WAITALL
|
||||
#define SELECT(a,b,c,d,e) select(a,b,c,d,e)
|
||||
#define SEND(a,b,c,d) send(a, (const int8 *)b, c, d)
|
||||
#define SENDTO(a,b,c,d,e,f) sendto(a, (const int8 *)b, c, d, e, f)
|
||||
#define SEND_FLAGS 0
|
||||
#define SENDFILE(a,b,c,d) sendfile(a, b, c, d)
|
||||
#define SET_SOCKET_ERROR(x,y) errno=y
|
||||
#define SOCKET_ERROR_INTERUPT EINTR
|
||||
#define SOCKET_ERROR_TIMEDOUT EAGAIN
|
||||
#define WRITE(a,b,c) write(a,b,c)
|
||||
#define WRITEV(a,b,c) writev(a, b, c)
|
||||
#define GETSOCKOPT(a,b,c,d,e) getsockopt((int)a,(int)b,(int)c,(void *)d,(socklen_t *)e)
|
||||
#define SETSOCKOPT(a,b,c,d,e) setsockopt((int)a,(int)b,(int)c,(const void *)d,(int)e)
|
||||
#define GETHOSTBYNAME(a) gethostbyname(a)
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* File Macros */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define STRUCT_STAT struct stat
|
||||
#define LSTAT(x,y) lstat(x,y)
|
||||
#define FILE_HANDLE FILE *
|
||||
#define CLEARERR(x) clearerr(x)
|
||||
#define FCLOSE(x) fclose(x)
|
||||
#define FEOF(x) feof(x)
|
||||
#define FERROR(x) ferror(x)
|
||||
#define FFLUSH(x) fflush(x)
|
||||
#define FILENO(s) fileno(s)
|
||||
#define FOPEN(x,y) fopen(x, y)
|
||||
//#define FREAD(a,b,c,d) fread(a, b, c, d)
|
||||
#define FSTAT(s, st) fstat(FILENO(s), st)
|
||||
//#define FWRITE(a,b,c,d) fwrite(a, b, c, d)
|
||||
#define STAT_BLK_SIZE(x) ((x).st_blksize)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Misc Macros */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if defined(WIN32)
|
||||
#define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x)
|
||||
#else
|
||||
#define GET_CLOCK_COUNT(x) gettimeofday(x, NULL)
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#define STRTOULL(x) _atoi64(x)
|
||||
#else
|
||||
#define STRTOULL(x) strtoull(x, NULL, 10)
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#define SNPRINTF _snprintf
|
||||
#define PRINTF printf
|
||||
#define VPRINTF vprintf
|
||||
#define FPRINTF fprintf
|
||||
#else
|
||||
#define SNPRINTF snprintf
|
||||
#define PRINTF printf
|
||||
#define VPRINTF vprintf
|
||||
#define FPRINTF fprintf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HOST_H__ */
|
331
examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp
Normal file
331
examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp
Normal file
@ -0,0 +1,331 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* PassiveSocket.cpp - Passive Socket Implementation */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "PassiveSocket.h"
|
||||
|
||||
|
||||
|
||||
CPassiveSocket::CPassiveSocket(CSocketType nType) : CSimpleSocket(nType)
|
||||
{
|
||||
}
|
||||
|
||||
bool CPassiveSocket::BindMulticast(const char *pInterface, const char *pGroup, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
#ifdef WIN32
|
||||
ULONG inAddr;
|
||||
#else
|
||||
int32 nReuse;
|
||||
in_addr_t inAddr;
|
||||
|
||||
nReuse = IPTOS_LOWDELAY;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set the following socket option SO_REUSEADDR. This will allow the file
|
||||
// descriptor to be reused immediately after the socket is closed instead
|
||||
// of setting in a TIMED_WAIT state.
|
||||
//--------------------------------------------------------------------------
|
||||
memset(&m_stMulticastGroup,0,sizeof(m_stMulticastGroup));
|
||||
m_stMulticastGroup.sin_family = AF_INET;
|
||||
m_stMulticastGroup.sin_port = htons(nPort);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If no IP Address (interface ethn) is supplied, or the loop back is
|
||||
// specified then bind to any interface, else bind to specified interface.
|
||||
//--------------------------------------------------------------------------
|
||||
if ((pInterface == NULL) || (!strlen(pInterface)))
|
||||
{
|
||||
m_stMulticastGroup.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((inAddr = inet_addr(pInterface)) != INADDR_NONE)
|
||||
{
|
||||
m_stMulticastGroup.sin_addr.s_addr = inAddr;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Bind to the specified port
|
||||
//--------------------------------------------------------------------------
|
||||
if (bind(m_socket, (struct sockaddr *)&m_stMulticastGroup, sizeof(m_stMulticastGroup)) == 0)
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Join the multicast group
|
||||
//----------------------------------------------------------------------
|
||||
m_stMulticastRequest.imr_multiaddr.s_addr = inet_addr(pGroup);
|
||||
m_stMulticastRequest.imr_interface.s_addr = m_stMulticastGroup.sin_addr.s_addr;
|
||||
|
||||
if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(void *)&m_stMulticastRequest,
|
||||
sizeof(m_stMulticastRequest)) == CSimpleSocket::SocketSuccess)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
m_timer.SetEndTime();
|
||||
}
|
||||
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If there was a socket error then close the socket to clean out the
|
||||
// connection in the backlog.
|
||||
//--------------------------------------------------------------------------
|
||||
TranslateSocketError();
|
||||
|
||||
if (bRetVal == false)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Listen() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CPassiveSocket::Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
#ifdef WIN32
|
||||
ULONG inAddr;
|
||||
#else
|
||||
int32 nReuse;
|
||||
in_addr_t inAddr;
|
||||
|
||||
nReuse = IPTOS_LOWDELAY;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set the following socket option SO_REUSEADDR. This will allow the file
|
||||
// descriptor to be reused immediately after the socket is closed instead
|
||||
// of setting in a TIMED_WAIT state.
|
||||
//--------------------------------------------------------------------------
|
||||
#ifdef _LINUX
|
||||
SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32));
|
||||
SETSOCKOPT(m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32));
|
||||
#endif
|
||||
|
||||
memset(&m_stServerSockaddr,0,sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If no IP Address (interface ethn) is supplied, or the loop back is
|
||||
// specified then bind to any interface, else bind to specified interface.
|
||||
//--------------------------------------------------------------------------
|
||||
if ((pAddr == NULL) || (!strlen(pAddr)))
|
||||
{
|
||||
m_stServerSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((inAddr = inet_addr(pAddr)) != INADDR_NONE)
|
||||
{
|
||||
m_stServerSockaddr.sin_addr.s_addr = inAddr;
|
||||
}
|
||||
}
|
||||
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Bind to the specified port
|
||||
//--------------------------------------------------------------------------
|
||||
if (bind(m_socket, (struct sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
|
||||
{
|
||||
if (m_nSocketType == CSimpleSocket::SocketTypeTcp)
|
||||
{
|
||||
if (listen(m_socket, nConnectionBacklog) != CSimpleSocket::SocketError)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If there was a socket error then close the socket to clean out the
|
||||
// connection in the backlog.
|
||||
//--------------------------------------------------------------------------
|
||||
TranslateSocketError();
|
||||
|
||||
if (bRetVal == false)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Accept() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
CActiveSocket *CPassiveSocket::Accept()
|
||||
{
|
||||
uint32 nSockLen;
|
||||
CActiveSocket *pClientSocket = NULL;
|
||||
SOCKET socket = CSimpleSocket::SocketError;
|
||||
|
||||
if (m_nSocketType != CSimpleSocket::SocketTypeTcp)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketProtocolError);
|
||||
return pClientSocket;
|
||||
}
|
||||
|
||||
pClientSocket = new CActiveSocket();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Wait for incoming connection.
|
||||
//--------------------------------------------------------------------------
|
||||
if (pClientSocket != NULL)
|
||||
{
|
||||
CSocketError socketErrno = SocketSuccess;
|
||||
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
nSockLen = sizeof(m_stClientSockaddr);
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen);
|
||||
|
||||
if (socket != -1)
|
||||
{
|
||||
pClientSocket->SetSocketHandle(socket);
|
||||
pClientSocket->TranslateSocketError();
|
||||
socketErrno = pClientSocket->GetSocketError();
|
||||
socklen_t nSockLen = sizeof(struct sockaddr);
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Store client and server IP and port information for this
|
||||
// connection.
|
||||
//-------------------------------------------------------------
|
||||
getpeername(m_socket, (struct sockaddr *)&pClientSocket->m_stClientSockaddr, &nSockLen);
|
||||
memcpy((void *)&pClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen);
|
||||
|
||||
memset(&pClientSocket->m_stServerSockaddr, 0, nSockLen);
|
||||
getsockname(m_socket, (struct sockaddr *)&pClientSocket->m_stServerSockaddr, &nSockLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateSocketError();
|
||||
socketErrno = GetSocketError();
|
||||
}
|
||||
|
||||
} while (socketErrno == CSimpleSocket::SocketInterrupted);
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
if (socketErrno != CSimpleSocket::SocketSuccess)
|
||||
{
|
||||
delete pClientSocket;
|
||||
pClientSocket = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pClientSocket;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Send() - Send data on a valid socket
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
int32 CPassiveSocket::Send(const uint8 *pBuf, size_t bytesToSend)
|
||||
{
|
||||
SetSocketError(SocketSuccess);
|
||||
m_nBytesSent = 0;
|
||||
|
||||
switch(m_nSocketType)
|
||||
{
|
||||
case CSimpleSocket::SocketTypeUdp:
|
||||
{
|
||||
if (IsSocketValid())
|
||||
{
|
||||
if ((bytesToSend > 0) && (pBuf != NULL))
|
||||
{
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0,
|
||||
(const sockaddr *)&m_stClientSockaddr,
|
||||
sizeof(m_stClientSockaddr));
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
if (m_nBytesSent == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CSimpleSocket::SocketTypeTcp:
|
||||
CSimpleSocket::Send(pBuf, bytesToSend);
|
||||
break;
|
||||
default:
|
||||
SetSocketError(SocketProtocolError);
|
||||
break;
|
||||
}
|
||||
|
||||
return m_nBytesSent;
|
||||
}
|
119
examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h
Normal file
119
examples/ThirdPartyLibs/clsocket/src/PassiveSocket.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* Socket.h - Passive Socket Decleration. */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifndef __PASSIVESOCKET_H__
|
||||
#define __PASSIVESOCKET_H__
|
||||
#include "ActiveSocket.h"
|
||||
|
||||
/// Provides a platform independent class to create a passive socket.
|
||||
/// A passive socket is used to create a "listening" socket. This type
|
||||
/// of object would be used when an application needs to wait for
|
||||
/// inbound connections. Support for CSimpleSocket::SocketTypeTcp,
|
||||
/// CSimpleSocket::SocketTypeUdp, and CSimpleSocket::SocketTypeRaw is handled
|
||||
/// in a similar fashion. The big difference is that the method
|
||||
/// CPassiveSocket::Accept should not be called on the latter two socket
|
||||
/// types.
|
||||
class CPassiveSocket : public CSimpleSocket {
|
||||
public:
|
||||
CPassiveSocket(CSocketType type = SocketTypeTcp);
|
||||
virtual ~CPassiveSocket() {
|
||||
Close();
|
||||
};
|
||||
|
||||
/// Extracts the first connection request on the queue of pending
|
||||
/// connections and creates a newly connected socket. Used with
|
||||
/// CSocketType CSimpleSocket::SocketTypeTcp. It is the responsibility of
|
||||
/// the caller to delete the returned object when finished.
|
||||
/// @return if successful a pointer to a newly created CActiveSocket object
|
||||
/// will be returned and the internal error condition of the CPassiveSocket
|
||||
/// object will be CPassiveSocket::SocketSuccess. If an error condition was encountered
|
||||
/// the NULL will be returned and one of the following error conditions will be set:
|
||||
/// CPassiveSocket::SocketEwouldblock, CPassiveSocket::SocketInvalidSocket,
|
||||
/// CPassiveSocket::SocketConnectionAborted, CPassiveSocket::SocketInterrupted
|
||||
/// CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketFirewallError
|
||||
virtual CActiveSocket *Accept(void);
|
||||
|
||||
/// Bind to a multicast group on a specified interface, multicast group, and port
|
||||
///
|
||||
/// @param pInterface - interface on which to bind.
|
||||
/// @param pGroup - multicast group address to bind.
|
||||
/// @param nPort - port on which multicast
|
||||
/// @return true if able to bind to interface and multicast group.
|
||||
/// If not successful, the false is returned and one of the following error
|
||||
/// condiitions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError,
|
||||
/// CPassiveSocket::SocketInvalidSocket. The following socket errors are for Linux/Unix
|
||||
/// derived systems only: CPassiveSocket::SocketInvalidSocketBuffer
|
||||
bool BindMulticast(const char *pInterface, const char *pGroup, uint16 nPort);
|
||||
|
||||
/// Create a listening socket at local ip address 'x.x.x.x' or 'localhost'
|
||||
/// if pAddr is NULL on port nPort.
|
||||
///
|
||||
/// @param pAddr specifies the IP address on which to listen.
|
||||
/// @param nPort specifies the port on which to listen.
|
||||
/// @param nConnectionBacklog specifies connection queue backlog (default 30,000)
|
||||
/// @return true if a listening socket was created.
|
||||
/// If not successful, the false is returned and one of the following error
|
||||
/// conditions will be set: CPassiveSocket::SocketAddressInUse, CPassiveSocket::SocketProtocolError,
|
||||
/// CPassiveSocket::SocketInvalidSocket. The following socket errors are for Linux/Unix
|
||||
/// derived systems only: CPassiveSocket::SocketInvalidSocketBuffer
|
||||
virtual bool Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog = 30000);
|
||||
|
||||
/// Attempts to send a block of data on an established connection.
|
||||
/// @param pBuf block of data to be sent.
|
||||
/// @param bytesToSend size of data block to be sent.
|
||||
/// @return number of bytes actually sent, return of zero means the
|
||||
/// connection has been shutdown on the other side, and a return of -1
|
||||
/// means that an error has occurred. If an error was signaled then one
|
||||
/// of the following error codes will be set: CPassiveSocket::SocketInvalidSocket,
|
||||
/// CPassiveSocket::SocketEwouldblock, SimpleSocket::SocketConnectionReset,
|
||||
/// CPassiveSocket::SocketInvalidSocketBuffer, CPassiveSocket::SocketInterrupted,
|
||||
/// CPassiveSocket::SocketProtocolError, CPassiveSocket::SocketNotconnected
|
||||
/// <br>\b Note: This function is used only for a socket of type
|
||||
/// CSimpleSocket::SocketTypeUdp
|
||||
virtual int32 Send(const uint8 *pBuf, size_t bytesToSend);
|
||||
|
||||
private:
|
||||
struct ip_mreq m_stMulticastRequest; /// group address for multicast
|
||||
|
||||
};
|
||||
|
||||
#endif // __PASSIVESOCKET_H__
|
1187
examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp
Normal file
1187
examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp
Normal file
File diff suppressed because it is too large
Load Diff
591
examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h
Normal file
591
examples/ThirdPartyLibs/clsocket/src/SimpleSocket.h
Normal file
@ -0,0 +1,591 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* SimpleSocket.h - Simple Socket base class decleration. */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifndef __SOCKET_H__
|
||||
#define __SOCKET_H__
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(_LINUX) || defined (_DARWIN)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef _LINUX
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
#ifdef _DARWIN
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#if defined(_LINUX) || defined (_DARWIN)
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
|
||||
#define IPTOS_LOWDELAY 0x10
|
||||
|
||||
#endif
|
||||
#include "Host.h"
|
||||
#include "StatTimer.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// General class macro definitions and typedefs
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET ~(0)
|
||||
#endif
|
||||
|
||||
#define SOCKET_SENDFILE_BLOCKSIZE 8192
|
||||
|
||||
/// Provides a platform independent class to for socket development.
|
||||
/// This class is designed to abstract socket communication development in a
|
||||
/// platform independent manner.
|
||||
/// - Socket types
|
||||
/// -# CActiveSocket Class
|
||||
/// -# CPassiveSocket Class
|
||||
class CSimpleSocket {
|
||||
public:
|
||||
/// Defines the three possible states for shuting down a socket.
|
||||
typedef enum
|
||||
{
|
||||
Receives = SHUT_RD, ///< Shutdown passive socket.
|
||||
Sends = SHUT_WR, ///< Shutdown active socket.
|
||||
Both = SHUT_RDWR ///< Shutdown both active and passive sockets.
|
||||
} CShutdownMode;
|
||||
|
||||
/// Defines the socket types defined by CSimpleSocket class.
|
||||
typedef enum
|
||||
{
|
||||
SocketTypeInvalid, ///< Invalid socket type.
|
||||
SocketTypeTcp, ///< Defines socket as TCP socket.
|
||||
SocketTypeUdp, ///< Defines socket as UDP socket.
|
||||
SocketTypeTcp6, ///< Defines socket as IPv6 TCP socket.
|
||||
SocketTypeUdp6, ///< Defines socket as IPv6 UDP socket.
|
||||
SocketTypeRaw ///< Provides raw network protocol access.
|
||||
} CSocketType;
|
||||
|
||||
/// Defines all error codes handled by the CSimpleSocket class.
|
||||
typedef enum
|
||||
{
|
||||
SocketError = -1, ///< Generic socket error translates to error below.
|
||||
SocketSuccess = 0, ///< No socket error.
|
||||
SocketInvalidSocket, ///< Invalid socket handle.
|
||||
SocketInvalidAddress, ///< Invalid destination address specified.
|
||||
SocketInvalidPort, ///< Invalid destination port specified.
|
||||
SocketConnectionRefused, ///< No server is listening at remote address.
|
||||
SocketTimedout, ///< Timed out while attempting operation.
|
||||
SocketEwouldblock, ///< Operation would block if socket were blocking.
|
||||
SocketNotconnected, ///< Currently not connected.
|
||||
SocketEinprogress, ///< Socket is non-blocking and the connection cannot be completed immediately
|
||||
SocketInterrupted, ///< Call was interrupted by a signal that was caught before a valid connection arrived.
|
||||
SocketConnectionAborted, ///< The connection has been aborted.
|
||||
SocketProtocolError, ///< Invalid protocol for operation.
|
||||
SocketFirewallError, ///< Firewall rules forbid connection.
|
||||
SocketInvalidSocketBuffer, ///< The receive buffer point outside the process's address space.
|
||||
SocketConnectionReset, ///< Connection was forcibly closed by the remote host.
|
||||
SocketAddressInUse, ///< Address already in use.
|
||||
SocketInvalidPointer, ///< Pointer type supplied as argument is invalid.
|
||||
SocketEunknown ///< Unknown error please report to mark@carrierlabs.com
|
||||
} CSocketError;
|
||||
|
||||
public:
|
||||
CSimpleSocket(CSocketType type = SocketTypeTcp);
|
||||
CSimpleSocket(CSimpleSocket &socket);
|
||||
|
||||
virtual ~CSimpleSocket()
|
||||
{
|
||||
if (m_pBuffer != NULL)
|
||||
{
|
||||
delete [] m_pBuffer;
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/// Initialize instance of CSocket. This method MUST be called before an
|
||||
/// object can be used. Errors : CSocket::SocketProtocolError,
|
||||
/// CSocket::SocketInvalidSocket,
|
||||
/// @return true if properly initialized.
|
||||
virtual bool Initialize(void);
|
||||
|
||||
/// Close socket
|
||||
/// @return true if successfully closed otherwise returns false.
|
||||
virtual bool Close(void);
|
||||
|
||||
/// Shutdown shut down socket send and receive operations
|
||||
/// CShutdownMode::Receives - Disables further receive operations.
|
||||
/// CShutdownMode::Sends - Disables further send operations.
|
||||
/// CShutdownBoth:: - Disables further send and receive operations.
|
||||
/// @param nShutdown specifies the type of shutdown.
|
||||
/// @return true if successfully shutdown otherwise returns false.
|
||||
virtual bool Shutdown(CShutdownMode nShutdown);
|
||||
|
||||
/// Examine the socket descriptor sets currently owned by the instance of
|
||||
/// the socket class (the readfds, writefds, and errorfds parameters) to
|
||||
/// see whether some of their descriptors are ready for reading, are ready
|
||||
/// for writing, or have an exceptional condition pending, respectively.
|
||||
/// Block until an event happens on the specified file descriptors.
|
||||
/// @return true if socket has data ready, or false if not ready or timed out.
|
||||
virtual bool Select(void) {
|
||||
return Select(0,0);
|
||||
};
|
||||
|
||||
/// Examine the socket descriptor sets currently owned by the instance of
|
||||
/// the socket class (the readfds, writefds, and errorfds parameters) to
|
||||
/// see whether some of their descriptors are ready for reading, are ready
|
||||
/// for writing, or have an exceptional condition pending, respectively.
|
||||
/// @param nTimeoutSec timeout in seconds for select.
|
||||
/// @param nTimeoutUSec timeout in micro seconds for select.
|
||||
/// @return true if socket has data ready, or false if not ready or timed out.
|
||||
virtual bool Select(int32 nTimeoutSec, int32 nTimeoutUSec);
|
||||
|
||||
/// Does the current instance of the socket object contain a valid socket
|
||||
/// descriptor.
|
||||
/// @return true if the socket object contains a valid socket descriptor.
|
||||
virtual bool IsSocketValid(void) {
|
||||
return (m_socket != SocketError);
|
||||
};
|
||||
|
||||
/// Provides a standard error code for cross platform development by
|
||||
/// mapping the operating system error to an error defined by the CSocket
|
||||
/// class.
|
||||
void TranslateSocketError(void);
|
||||
|
||||
/// Returns a human-readable description of the given error code
|
||||
/// or the last error code of a socket
|
||||
static const char *DescribeError(CSocketError err);
|
||||
inline const char *DescribeError() {
|
||||
return DescribeError(m_socketErrno);
|
||||
};
|
||||
|
||||
/// Attempts to receive a block of data on an established connection.
|
||||
/// @param nMaxBytes maximum number of bytes to receive.
|
||||
/// @param pBuffer, memory where to receive the data,
|
||||
/// NULL receives to internal buffer returned with GetData()
|
||||
/// Non-NULL receives directly there, but GetData() will return WRONG ptr!
|
||||
/// @return number of bytes actually received.
|
||||
/// @return of zero means the connection has been shutdown on the other side.
|
||||
/// @return of -1 means that an error has occurred.
|
||||
virtual int32 Receive(int32 nMaxBytes = 1, uint8 * pBuffer = 0);
|
||||
|
||||
/// Attempts to send a block of data on an established connection.
|
||||
/// @param pBuf block of data to be sent.
|
||||
/// @param bytesToSend size of data block to be sent.
|
||||
/// @return number of bytes actually sent.
|
||||
/// @return of zero means the connection has been shutdown on the other side.
|
||||
/// @return of -1 means that an error has occurred.
|
||||
virtual int32 Send(const uint8 *pBuf, size_t bytesToSend);
|
||||
|
||||
/// Attempts to send at most nNumItem blocks described by sendVector
|
||||
/// to the socket descriptor associated with the socket object.
|
||||
/// @param sendVector pointer to an array of iovec structures
|
||||
/// @param nNumItems number of items in the vector to process
|
||||
/// <br>\b NOTE: Buffers are processed in the order specified.
|
||||
/// @return number of bytes actually sent, return of zero means the
|
||||
/// connection has been shutdown on the other side, and a return of -1
|
||||
/// means that an error has occurred.
|
||||
virtual int32 Send(const struct iovec *sendVector, int32 nNumItems);
|
||||
|
||||
/// Copies data between one file descriptor and another.
|
||||
/// On some systems this copying is done within the kernel, and thus is
|
||||
/// more efficient than the combination of CSimpleSocket::Send and
|
||||
/// CSimpleSocket::Receive, which would require transferring data to and
|
||||
/// from user space.
|
||||
/// <br>\b Note: This is available on all implementations, but the kernel
|
||||
/// implementation is only available on Unix type systems.
|
||||
/// @param nOutFd descriptor opened for writing.
|
||||
/// @param nInFd descriptor opened for reading.
|
||||
/// @param pOffset from which to start reading data from input file.
|
||||
/// @param nCount number of bytes to copy between file descriptors.
|
||||
/// @return number of bytes written to the out socket descriptor.
|
||||
virtual int32 SendFile(int32 nOutFd, int32 nInFd, off_t *pOffset, int32 nCount);
|
||||
|
||||
/// Returns blocking/non-blocking state of socket.
|
||||
/// @return true if the socket is non-blocking, else return false.
|
||||
bool IsNonblocking(void) {
|
||||
return (m_bIsBlocking == false);
|
||||
};
|
||||
|
||||
/// Set the socket to blocking.
|
||||
/// @return true if successful set to blocking, else return false;
|
||||
bool SetBlocking(void);
|
||||
|
||||
/// Set the socket as non-blocking.
|
||||
/// @return true if successful set to non-blocking, else return false;
|
||||
bool SetNonblocking(void);
|
||||
|
||||
/// Get a pointer to internal receive buffer. The user MUST not free this
|
||||
/// pointer when finished. This memory is managed internally by the CSocket
|
||||
/// class.
|
||||
/// @return pointer to data if valid, else returns NULL.
|
||||
uint8 *GetData(void) {
|
||||
return m_pBuffer;
|
||||
};
|
||||
|
||||
/// Returns the number of bytes received on the last call to
|
||||
/// CSocket::Receive().
|
||||
/// @return number of bytes received.
|
||||
int32 GetBytesReceived(void) {
|
||||
return m_nBytesReceived;
|
||||
};
|
||||
|
||||
/// Returns the number of bytes sent on the last call to
|
||||
/// CSocket::Send().
|
||||
/// @return number of bytes sent.
|
||||
int32 GetBytesSent(void) {
|
||||
return m_nBytesSent;
|
||||
};
|
||||
|
||||
/// Controls the actions taken when CSimpleSocket::Close is executed on a
|
||||
/// socket object that has unsent data. The default value for this option
|
||||
/// is \b off.
|
||||
/// - Following are the three possible scenarios.
|
||||
/// -# \b bEnable is false, CSimpleSocket::Close returns immediately, but
|
||||
/// any unset data is transmitted (after CSimpleSocket::Close returns)
|
||||
/// -# \b bEnable is true and \b nTime is zero, CSimpleSocket::Close return
|
||||
/// immediately and any unsent data is discarded.
|
||||
/// -# \b bEnable is true and \b nTime is nonzero, CSimpleSocket::Close does
|
||||
/// not return until all unsent data is transmitted (or the connection is
|
||||
/// Closed by the remote system).
|
||||
/// <br><p>
|
||||
/// @param bEnable true to enable option false to disable option.
|
||||
/// @param nTime time in seconds to linger.
|
||||
/// @return true if option successfully set
|
||||
bool SetOptionLinger(bool bEnable, uint16 nTime);
|
||||
|
||||
/// Tells the kernel that even if this port is busy (in the TIME_WAIT state),
|
||||
/// go ahead and reuse it anyway. If it is busy, but with another state,
|
||||
/// you will still get an address already in use error.
|
||||
/// @return true if option successfully set
|
||||
bool SetOptionReuseAddr();
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of seconds a
|
||||
/// call to CSimpleSocket::Open waits until it completes.
|
||||
/// @return the length of time in seconds
|
||||
int32 GetConnectTimeoutSec(void) {
|
||||
return m_stConnectTimeout.tv_sec;
|
||||
};
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of microseconds
|
||||
/// a call to CSimpleSocket::Open waits until it completes.
|
||||
/// @return the length of time in microseconds
|
||||
int32 GetConnectTimeoutUSec(void) {
|
||||
return m_stConnectTimeout.tv_usec;
|
||||
};
|
||||
|
||||
/// Sets the timeout value that specifies the maximum amount of time a call
|
||||
/// to CSimpleSocket::Receive waits until it completes. Use the method
|
||||
/// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.
|
||||
/// If a call to CSimpleSocket::Receive has blocked for the specified length of
|
||||
/// time without receiving additional data, it returns with a partial count
|
||||
/// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data
|
||||
/// were received.
|
||||
/// @param nConnectTimeoutSec of timeout in seconds.
|
||||
/// @param nConnectTimeoutUsec of timeout in microseconds.
|
||||
/// @return true if socket connection timeout was successfully set.
|
||||
void SetConnectTimeout(int32 nConnectTimeoutSec, int32 nConnectTimeoutUsec = 0)
|
||||
{
|
||||
m_stConnectTimeout.tv_sec = nConnectTimeoutSec;
|
||||
m_stConnectTimeout.tv_usec = nConnectTimeoutUsec;
|
||||
};
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of seconds a
|
||||
/// a call to CSimpleSocket::Receive waits until it completes.
|
||||
/// @return the length of time in seconds
|
||||
int32 GetReceiveTimeoutSec(void) {
|
||||
return m_stRecvTimeout.tv_sec;
|
||||
};
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of microseconds
|
||||
/// a call to CSimpleSocket::Receive waits until it completes.
|
||||
/// @return the length of time in microseconds
|
||||
int32 GetReceiveTimeoutUSec(void) {
|
||||
return m_stRecvTimeout.tv_usec;
|
||||
};
|
||||
|
||||
/// Sets the timeout value that specifies the maximum amount of time a call
|
||||
/// to CSimpleSocket::Receive waits until it completes. Use the method
|
||||
/// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.
|
||||
/// If a call to CSimpleSocket::Receive has blocked for the specified length of
|
||||
/// time without receiving additional data, it returns with a partial count
|
||||
/// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data
|
||||
/// were received.
|
||||
/// @param nRecvTimeoutSec of timeout in seconds.
|
||||
/// @param nRecvTimeoutUsec of timeout in microseconds.
|
||||
/// @return true if socket timeout was successfully set.
|
||||
bool SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec = 0);
|
||||
|
||||
/// Enable/disable multicast for a socket. This options is only valid for
|
||||
/// socket descriptors of type CSimpleSocket::SocketTypeUdp.
|
||||
/// @return true if multicast was enabled or false if socket type is not
|
||||
/// CSimpleSocket::SocketTypeUdp and the error will be set to
|
||||
/// CSimpleSocket::SocketProtocolError
|
||||
bool SetMulticast(bool bEnable, uint8 multicastTTL = 1);
|
||||
|
||||
/// Return true if socket is multicast or false is socket is unicast
|
||||
/// @return true if multicast is enabled
|
||||
bool GetMulticast() {
|
||||
return m_bIsMulticast;
|
||||
};
|
||||
|
||||
/// Bind socket to a specific interface when using multicast.
|
||||
/// @return true if successfully bound to interface
|
||||
bool BindInterface(const char *pInterface);
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of seconds a
|
||||
/// a call to CSimpleSocket::Send waits until it completes.
|
||||
/// @return the length of time in seconds
|
||||
int32 GetSendTimeoutSec(void) {
|
||||
return m_stSendTimeout.tv_sec;
|
||||
};
|
||||
|
||||
/// Gets the timeout value that specifies the maximum number of microseconds
|
||||
/// a call to CSimpleSocket::Send waits until it completes.
|
||||
/// @return the length of time in microseconds
|
||||
int32 GetSendTimeoutUSec(void) {
|
||||
return m_stSendTimeout.tv_usec;
|
||||
};
|
||||
|
||||
/// Gets the timeout value that specifies the maximum amount of time a call
|
||||
/// to CSimpleSocket::Send waits until it completes.
|
||||
/// @return the length of time in seconds
|
||||
bool SetSendTimeout(int32 nSendTimeoutSec, int32 nSendTimeoutUsec = 0);
|
||||
|
||||
/// Returns the last error that occured for the instace of the CSimpleSocket
|
||||
/// instance. This method should be called immediately to retrieve the
|
||||
/// error code for the failing mehtod call.
|
||||
/// @return last error that occured.
|
||||
CSocketError GetSocketError(void) {
|
||||
return m_socketErrno;
|
||||
};
|
||||
/*
|
||||
CSocketError GetSocketError(void) {
|
||||
CSocketError err = m_socketErrno;
|
||||
m_socketErrno = SocketSuccess;
|
||||
return err;
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
/// Get the total time the of the last operation in milliseconds.
|
||||
/// @return number of milliseconds of last operation.
|
||||
uint32 GetTotalTimeMs() {
|
||||
return m_timer.GetMilliSeconds();
|
||||
};
|
||||
|
||||
/// Get the total time the of the last operation in microseconds.
|
||||
/// @return number of microseconds or last operation.
|
||||
uint32 GetTotalTimeUsec() {
|
||||
return m_timer.GetMicroSeconds();
|
||||
};
|
||||
|
||||
/// Return Differentiated Services Code Point (DSCP) value currently set on the socket object.
|
||||
/// @return DSCP for current socket object.
|
||||
/// <br><br> \b NOTE: Windows special notes http://support.microsoft.com/kb/248611.
|
||||
int GetSocketDscp(void);
|
||||
|
||||
/// Set Differentiated Services Code Point (DSCP) for socket object.
|
||||
/// @param nDscp value of TOS setting which will be converted to DSCP
|
||||
/// @return true if DSCP value was properly set
|
||||
/// <br><br> \b NOTE: Windows special notes http://support.microsoft.com/kb/248611.
|
||||
bool SetSocketDscp(int nDscp);
|
||||
|
||||
/// Return socket descriptor
|
||||
/// @return socket descriptor which is a signed 32 bit integer.
|
||||
SOCKET GetSocketDescriptor() {
|
||||
return m_socket;
|
||||
};
|
||||
|
||||
/// Return socket descriptor
|
||||
/// @return socket descriptor which is a signed 32 bit integer.
|
||||
CSocketType GetSocketType() {
|
||||
return m_nSocketType;
|
||||
};
|
||||
|
||||
/// Returns clients Internet host address as a string in standard numbers-and-dots notation.
|
||||
/// @return NULL if invalid
|
||||
const char *GetClientAddr() {
|
||||
return inet_ntoa(m_stClientSockaddr.sin_addr);
|
||||
};
|
||||
|
||||
/// Returns the port number on which the client is connected.
|
||||
/// @return client port number.
|
||||
uint16 GetClientPort() {
|
||||
return m_stClientSockaddr.sin_port;
|
||||
};
|
||||
|
||||
/// Returns server Internet host address as a string in standard numbers-and-dots notation.
|
||||
/// @return NULL if invalid
|
||||
const char *GetServerAddr() {
|
||||
return inet_ntoa(m_stServerSockaddr.sin_addr);
|
||||
};
|
||||
|
||||
/// Returns the port number on which the server is connected.
|
||||
/// @return server port number.
|
||||
uint16 GetServerPort() {
|
||||
return ntohs(m_stServerSockaddr.sin_port);
|
||||
};
|
||||
|
||||
/// Get the TCP receive buffer window size for the current socket object.
|
||||
/// <br><br>\b NOTE: Linux will set the receive buffer to twice the value passed.
|
||||
/// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.
|
||||
uint32 GetReceiveWindowSize() {
|
||||
return GetWindowSize(SO_RCVBUF);
|
||||
};
|
||||
|
||||
/// Get the TCP send buffer window size for the current socket object.
|
||||
/// <br><br>\b NOTE: Linux will set the send buffer to twice the value passed.
|
||||
/// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.
|
||||
uint32 GetSendWindowSize() {
|
||||
return GetWindowSize(SO_SNDBUF);
|
||||
};
|
||||
|
||||
/// Set the TCP receive buffer window size for the current socket object.
|
||||
/// <br><br>\b NOTE: Linux will set the receive buffer to twice the value passed.
|
||||
/// @return zero on failure else the number of bytes of the TCP send buffer window size if successful.
|
||||
uint32 SetReceiveWindowSize(uint32 nWindowSize) {
|
||||
return SetWindowSize(SO_RCVBUF, nWindowSize);
|
||||
};
|
||||
|
||||
/// Set the TCP send buffer window size for the current socket object.
|
||||
/// <br><br>\b NOTE: Linux will set the send buffer to twice the value passed.
|
||||
/// @return zero on failure else the number of bytes of the TCP send buffer window size if successful.
|
||||
uint32 SetSendWindowSize(uint32 nWindowSize) {
|
||||
return SetWindowSize(SO_SNDBUF, nWindowSize);
|
||||
};
|
||||
|
||||
/// Disable the Nagle algorithm (Set TCP_NODELAY to true)
|
||||
/// @return false if failed to set socket option otherwise return true;
|
||||
bool DisableNagleAlgoritm();
|
||||
|
||||
/// Enable the Nagle algorithm (Set TCP_NODELAY to false)
|
||||
/// @return false if failed to set socket option otherwise return true;
|
||||
bool EnableNagleAlgoritm();
|
||||
|
||||
|
||||
protected:
|
||||
/// Set internal socket error to that specified error
|
||||
/// @param error type of error
|
||||
void SetSocketError(CSimpleSocket::CSocketError error) {
|
||||
m_socketErrno = error;
|
||||
};
|
||||
|
||||
/// Set object socket handle to that specified as parameter
|
||||
/// @param socket value of socket descriptor
|
||||
void SetSocketHandle(SOCKET socket) {
|
||||
m_socket = socket;
|
||||
};
|
||||
|
||||
private:
|
||||
/// Generic function used to get the send/receive window size
|
||||
/// @return zero on failure else the number of bytes of the TCP window size if successful.
|
||||
uint32 GetWindowSize(uint32 nOptionName);
|
||||
|
||||
/// Generic function used to set the send/receive window size
|
||||
/// @return zero on failure else the number of bytes of the TCP window size if successful.
|
||||
uint32 SetWindowSize(uint32 nOptionName, uint32 nWindowSize);
|
||||
|
||||
|
||||
/// Attempts to send at most nNumItem blocks described by sendVector
|
||||
/// to the socket descriptor associated with the socket object.
|
||||
/// @param sendVector pointer to an array of iovec structures
|
||||
/// @param nNumItems number of items in the vector to process
|
||||
/// <br>\b Note: This implementation is for systems that don't natively
|
||||
/// support this functionality.
|
||||
/// @return number of bytes actually sent, return of zero means the
|
||||
/// connection has been shutdown on the other side, and a return of -1
|
||||
/// means that an error has occurred.
|
||||
int32 Writev(const struct iovec *pVector, size_t nCount);
|
||||
|
||||
/// Flush the socket descriptor owned by the object.
|
||||
/// @return true data was successfully sent, else return false;
|
||||
bool Flush();
|
||||
|
||||
CSimpleSocket *operator=(CSimpleSocket &socket);
|
||||
|
||||
protected:
|
||||
SOCKET m_socket; /// socket handle
|
||||
CSocketError m_socketErrno; /// number of last error
|
||||
uint8 *m_pBuffer; /// internal send/receive buffer
|
||||
int32 m_nBufferSize; /// size of internal send/receive buffer
|
||||
int32 m_nSocketDomain; /// socket type PF_INET, PF_INET6
|
||||
CSocketType m_nSocketType; /// socket type - UDP, TCP or RAW
|
||||
int32 m_nBytesReceived; /// number of bytes received
|
||||
int32 m_nBytesSent; /// number of bytes sent
|
||||
uint32 m_nFlags; /// socket flags
|
||||
bool m_bIsBlocking; /// is socket blocking
|
||||
bool m_bIsMulticast; /// is the UDP socket multicast;
|
||||
struct timeval m_stConnectTimeout; /// connection timeout
|
||||
struct timeval m_stRecvTimeout; /// receive timeout
|
||||
struct timeval m_stSendTimeout; /// send timeout
|
||||
struct sockaddr_in m_stServerSockaddr; /// server address
|
||||
struct sockaddr_in m_stClientSockaddr; /// client address
|
||||
struct sockaddr_in m_stMulticastGroup; /// multicast group to bind to
|
||||
struct linger m_stLinger; /// linger flag
|
||||
CStatTimer m_timer; /// internal statistics.
|
||||
#ifdef WIN32
|
||||
WSADATA m_hWSAData; /// Windows
|
||||
#endif
|
||||
fd_set m_writeFds; /// write file descriptor set
|
||||
fd_set m_readFds; /// read file descriptor set
|
||||
fd_set m_errorFds; /// error file descriptor set
|
||||
};
|
||||
|
||||
|
||||
#endif /* __SOCKET_H__ */
|
||||
|
114
examples/ThirdPartyLibs/clsocket/src/StatTimer.h
Normal file
114
examples/ThirdPartyLibs/clsocket/src/StatTimer.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* StatTimer.h: interface for the CStatTimer class. */
|
||||
/* */
|
||||
/* Author: Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2006 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifndef __CSTATTIMER_H__
|
||||
#define __CSTATTIMER_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if WIN32
|
||||
#include <Winsock2.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "Host.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#define GET_CLOCK_COUNT(x) QueryPerformanceCounter((LARGE_INTEGER *)x)
|
||||
#else
|
||||
#define GET_CLOCK_COUNT(x) gettimeofday(x, NULL)
|
||||
#endif
|
||||
|
||||
#define MILLISECONDS_CONVERSION 1000
|
||||
#define MICROSECONDS_CONVERSION 1000000
|
||||
|
||||
/// Class to abstract socket communications in a cross platform manner.
|
||||
/// This class is designed
|
||||
class CStatTimer {
|
||||
public:
|
||||
CStatTimer()
|
||||
{
|
||||
};
|
||||
|
||||
~CStatTimer()
|
||||
{
|
||||
};
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
memset(&m_startTime, 0, sizeof(struct timeval));
|
||||
memset(&m_endTime, 0, sizeof(struct timeval));
|
||||
};
|
||||
|
||||
struct timeval GetStartTime() { return m_startTime; };
|
||||
void SetStartTime() { GET_CLOCK_COUNT(&m_startTime); };
|
||||
|
||||
struct timeval GetEndTime() { return m_endTime; };
|
||||
void SetEndTime() { GET_CLOCK_COUNT(&m_endTime); };
|
||||
|
||||
uint32 GetMilliSeconds() { return (CalcTotalUSec() / MILLISECONDS_CONVERSION); };
|
||||
uint32 GetMicroSeconds() { return (CalcTotalUSec()); };
|
||||
uint32 GetSeconds() { return (CalcTotalUSec() / MICROSECONDS_CONVERSION); };
|
||||
|
||||
uint32 GetCurrentTime()
|
||||
{
|
||||
struct timeval tmpTime;
|
||||
GET_CLOCK_COUNT(&tmpTime);
|
||||
return ((tmpTime.tv_sec * MICROSECONDS_CONVERSION) + tmpTime.tv_usec);
|
||||
};
|
||||
|
||||
private:
|
||||
uint32 CalcTotalUSec() { return (((m_endTime.tv_sec - m_startTime.tv_sec) * MICROSECONDS_CONVERSION) +
|
||||
(m_endTime.tv_usec - m_startTime.tv_usec)); };
|
||||
|
||||
|
||||
private:
|
||||
struct timeval m_startTime;
|
||||
struct timeval m_endTime;
|
||||
};
|
||||
|
||||
#endif // __CSTATTIMER_H__
|
@ -4,6 +4,7 @@ INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/enet/include
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/clsocket/src
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
)
|
||||
IF(BUILD_PYBULLET_NUMPY)
|
||||
@ -79,6 +80,9 @@ SET(pybullet_SRCS
|
||||
../../examples/MultiThreading/b3ThreadSupportInterface.cpp
|
||||
|
||||
)
|
||||
IF(BUILD_PYBULLET_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DBT_ENABLE_CLSOCKET)
|
||||
ENDIF(BUILD_PYBULLET_CLSOCKET)
|
||||
|
||||
IF(WIN32)
|
||||
LINK_LIBRARIES(
|
||||
@ -87,15 +91,27 @@ IF(WIN32)
|
||||
IF(BUILD_PYBULLET_ENET)
|
||||
ADD_DEFINITIONS(-DWIN32 -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_PYBULLET_ENET)
|
||||
IF(BUILD_PYBULLET_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DWIN32)
|
||||
ENDIF(BUILD_PYBULLET_CLSOCKET)
|
||||
|
||||
ELSE(WIN32)
|
||||
IF(BUILD_PYBULLET_ENET)
|
||||
ADD_DEFINITIONS(-DHAS_SOCKLEN_T -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_PYBULLET_ENET)
|
||||
|
||||
IF(BUILD_PYBULLET_CLSOCKET)
|
||||
IF(APPLE)
|
||||
ADD_DEFINITIONS(-D_DARWIN)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-D_LINUX)
|
||||
ENDIF()
|
||||
ENDIF(BUILD_PYBULLET_CLSOCKET)
|
||||
ENDIF(WIN32)
|
||||
|
||||
|
||||
IF(BUILD_PYBULLET_ENET)
|
||||
ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}
|
||||
set(pybullet_SRCS ${pybullet_SRCS}
|
||||
../../examples/SharedMemory/PhysicsClientUDP.cpp
|
||||
../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp
|
||||
../../examples/SharedMemory/PhysicsClientUDP.h
|
||||
@ -110,10 +126,22 @@ IF(BUILD_PYBULLET_ENET)
|
||||
../../examples/ThirdPartyLibs/enet/peer.c
|
||||
../../examples/ThirdPartyLibs/enet/protocol.c
|
||||
)
|
||||
ELSE(BUILD_PYBULLET_ENET)
|
||||
ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS})
|
||||
ENDIF(BUILD_PYBULLET_ENET)
|
||||
|
||||
IF(BUILD_PYBULLET_CLSOCKET)
|
||||
set(pybullet_SRCS ${pybullet_SRCS}
|
||||
../../examples/SharedMemory/PhysicsClientTCP.cpp
|
||||
../../examples/SharedMemory/PhysicsClientTCP.h
|
||||
../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp
|
||||
../../examples/SharedMemory/PhysicsClientTCP_C_API.h
|
||||
../../examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp
|
||||
../../examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp
|
||||
../../examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS})
|
||||
|
||||
SET_TARGET_PROPERTIES(pybullet PROPERTIES PREFIX "")
|
||||
SET_TARGET_PROPERTIES(pybullet PROPERTIES POSTFIX "")
|
||||
|
||||
@ -123,7 +151,7 @@ SET_TARGET_PROPERTIES(pybullet PROPERTIES DEBUG_POSTFIX "_d")
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
IF(BUILD_PYBULLET_ENET)
|
||||
IF(BUILD_PYBULLET_ENET OR BUILD_PYBULLET_CLSOCKET)
|
||||
TARGET_LINK_LIBRARIES(pybullet ws2_32 )
|
||||
ENDIF(BUILD_PYBULLET_ENET)
|
||||
|
||||
|
@ -59,6 +59,32 @@ if not _OPTIONS["no-enet"] then
|
||||
defines {"BT_ENABLE_ENET"}
|
||||
end
|
||||
|
||||
if not _OPTIONS["no-clsocket"] then
|
||||
|
||||
includedirs {"../../examples/ThirdPartyLibs/clsocket/src"}
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
links {"clsocket"}
|
||||
|
||||
files {
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.h",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.h",
|
||||
}
|
||||
defines {"BT_ENABLE_CLSOCKET"}
|
||||
end
|
||||
|
||||
|
||||
files {
|
||||
"pybullet.c",
|
||||
|
@ -5,6 +5,10 @@
|
||||
#include "../SharedMemory/PhysicsClientUDP_C_API.h"
|
||||
#endif //BT_ENABLE_ENET
|
||||
|
||||
#ifdef BT_ENABLE_CLSOCKET
|
||||
#include "../SharedMemory/PhysicsClientTCP_C_API.h"
|
||||
#endif //BT_ENABLE_CLSOCKET
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Python/Python.h>
|
||||
#else
|
||||
@ -25,6 +29,7 @@ enum eCONNECT_METHOD {
|
||||
eCONNECT_DIRECT = 2,
|
||||
eCONNECT_SHARED_MEMORY = 3,
|
||||
eCONNECT_UDP = 4,
|
||||
eCONNECT_TCP = 5,
|
||||
};
|
||||
|
||||
static PyObject* SpamError;
|
||||
@ -227,7 +232,9 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
{
|
||||
|
||||
int key = SHARED_MEMORY_KEY;
|
||||
int port = 1234;
|
||||
int udpPort = 1234;
|
||||
int tcpPort = 6667;
|
||||
|
||||
const char* hostName = "localhost";
|
||||
|
||||
int size = PySequence_Size(args);
|
||||
@ -236,7 +243,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
if (!PyArg_ParseTuple(args, "i", &method)) {
|
||||
PyErr_SetString(SpamError,
|
||||
"connectPhysicsServer expected argument GUI, "
|
||||
"DIRECT, SHARED_MEMORY or UDP");
|
||||
"DIRECT, SHARED_MEMORY, UDP or TCP");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -250,7 +257,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
if (sPhysicsClientsGUI[i] ==eCONNECT_GUI)
|
||||
{
|
||||
PyErr_SetString(SpamError,
|
||||
"Only one local in-process GUI connection allowed. Use DIRECT connection mode or start a separate GUI physics server (ExampleBrowser, App_SharedMemoryPhysics_GUI, App_SharedMemoryPhysics_VR) and connect over SHARED_MEMORY or UDP instead.");
|
||||
"Only one local in-process GUI connection allowed. Use DIRECT connection mode or start a separate GUI physics server (ExampleBrowser, App_SharedMemoryPhysics_GUI, App_SharedMemoryPhysics_VR) and connect over SHARED_MEMORY, UDP or TCP instead.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -275,12 +282,18 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
|
||||
if (size == 3)
|
||||
{
|
||||
int port = -1;
|
||||
if (!PyArg_ParseTuple(args, "isi", &method, &hostName, &port))
|
||||
{
|
||||
PyErr_SetString(SpamError,
|
||||
"connectPhysicsServer 3 arguments: method, hostname, port");
|
||||
return NULL;
|
||||
}
|
||||
if (port>=0)
|
||||
{
|
||||
udpPort = port;
|
||||
tcpPort = port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +321,7 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
{
|
||||
#ifdef BT_ENABLE_ENET
|
||||
|
||||
sm = b3ConnectPhysicsUDP(hostName, port);
|
||||
sm = b3ConnectPhysicsUDP(hostName, udpPort);
|
||||
#else
|
||||
PyErr_SetString(SpamError, "UDP is not enabled in this pybullet build");
|
||||
return NULL;
|
||||
@ -316,6 +329,20 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args, P
|
||||
|
||||
break;
|
||||
}
|
||||
case eCONNECT_TCP:
|
||||
{
|
||||
#ifdef BT_ENABLE_CLSOCKET
|
||||
|
||||
sm = b3ConnectPhysicsTCP(hostName, tcpPort);
|
||||
#else
|
||||
PyErr_SetString(SpamError, "TCP is not enabled in this pybullet build");
|
||||
return NULL;
|
||||
#endif //BT_ENABLE_CLSOCKET
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
default: {
|
||||
PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument");
|
||||
@ -5126,6 +5153,7 @@ initpybullet(void)
|
||||
PyModule_AddIntConstant(m, "DIRECT", eCONNECT_DIRECT); // user read
|
||||
PyModule_AddIntConstant(m, "GUI", eCONNECT_GUI); // user read
|
||||
PyModule_AddIntConstant(m, "UDP", eCONNECT_UDP); // user read
|
||||
PyModule_AddIntConstant(m, "TCP", eCONNECT_TCP); // user read
|
||||
|
||||
PyModule_AddIntConstant(m, "JOINT_REVOLUTE", eRevoluteType); // user read
|
||||
PyModule_AddIntConstant(m, "JOINT_PRISMATIC", ePrismaticType); // user read
|
||||
|
@ -28,6 +28,120 @@ project ("Test_SharedMemoryPhysicsClient")
|
||||
"../../examples/Utils/b3ResourcePath.cpp",
|
||||
"../../examples/Utils/b3ResourcePath.h",
|
||||
}
|
||||
|
||||
project ("Test_PhysicsClientUDP")
|
||||
|
||||
language "C++"
|
||||
kind "ConsoleApp"
|
||||
|
||||
includedirs {
|
||||
"../../src",
|
||||
"../../examples",
|
||||
"../../examples/ThirdPartyLibs/enet/include"
|
||||
}
|
||||
links {
|
||||
"enet",
|
||||
"BulletFileLoader",
|
||||
"Bullet3Common",
|
||||
"LinearMath"
|
||||
}
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
|
||||
defines {"PHYSICS_UDP"}
|
||||
|
||||
files {
|
||||
"test.c",
|
||||
"../../examples/SharedMemory/PhysicsClient.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClient.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP.h",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.h",
|
||||
"../../examples/SharedMemory/Win32SharedMemory.cpp",
|
||||
"../../examples/SharedMemory/Win32SharedMemory.h",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.h",
|
||||
"../../examples/Utils/b3ResourcePath.cpp",
|
||||
"../../examples/Utils/b3ResourcePath.h",
|
||||
"../../examples/SharedMemory/PhysicsDirect.cpp",
|
||||
"../../examples/Utils/b3Clock.cpp",
|
||||
"../../examples/MultiThreading/b3PosixThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3Win32ThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3ThreadSupportInterface.cpp",
|
||||
}
|
||||
|
||||
|
||||
project ("Test_PhysicsClientTCP")
|
||||
|
||||
language "C++"
|
||||
kind "ConsoleApp"
|
||||
|
||||
includedirs {
|
||||
"../../src",
|
||||
"../../examples",
|
||||
"../../examples/ThirdPartyLibs/clsocket/src"
|
||||
}
|
||||
links {
|
||||
"clsocket",
|
||||
"BulletFileLoader",
|
||||
"Bullet3Common",
|
||||
"LinearMath"
|
||||
}
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32","_WINSOCK_DEPRECATED_NO_WARNINGS" }
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
defines {"PHYSICS_TCP"}
|
||||
|
||||
files {
|
||||
"test.c",
|
||||
"../../examples/SharedMemory/PhysicsClient.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClient.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.h",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.h",
|
||||
"../../examples/SharedMemory/Win32SharedMemory.cpp",
|
||||
"../../examples/SharedMemory/Win32SharedMemory.h",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.h",
|
||||
"../../examples/Utils/b3ResourcePath.cpp",
|
||||
"../../examples/Utils/b3ResourcePath.h",
|
||||
"../../examples/SharedMemory/PhysicsDirect.cpp",
|
||||
"../../examples/Utils/b3Clock.cpp",
|
||||
"../../examples/MultiThreading/b3PosixThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3Win32ThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3ThreadSupportInterface.cpp",
|
||||
}
|
||||
|
||||
|
||||
project ("Test_PhysicsServerLoopBack")
|
||||
|
||||
|
@ -8,6 +8,10 @@
|
||||
#include "SharedMemory/PhysicsClientUDP_C_API.h"
|
||||
#endif//PHYSICS_UDP
|
||||
|
||||
#ifdef PHYSICS_TCP
|
||||
#include "SharedMemory/PhysicsClientTCP_C_API.h"
|
||||
#endif//PHYSICS_TCP
|
||||
|
||||
#ifdef PHYSICS_LOOP_BACK
|
||||
#include "SharedMemory/PhysicsLoopBackC_API.h"
|
||||
#endif //PHYSICS_LOOP_BACK
|
||||
@ -256,6 +260,7 @@ void testSharedMemory(b3PhysicsClientHandle sm)
|
||||
b3RequestCameraImageSetPixelResolution(command, width, height);
|
||||
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command);
|
||||
}
|
||||
|
||||
if (b3CanSubmitCommand(sm))
|
||||
{
|
||||
b3SharedMemoryStatusHandle state = b3SubmitClientCommandAndWaitStatus(sm, b3RequestActualStateCommandInit(sm,bodyIndex));
|
||||
@ -344,6 +349,10 @@ int main(int argc, char* argv[])
|
||||
b3PhysicsClientHandle sm = b3ConnectPhysicsUDP("localhost",1234);
|
||||
#endif //PHYSICS_UDP
|
||||
|
||||
#ifdef PHYSICS_TCP
|
||||
b3PhysicsClientHandle sm = b3ConnectPhysicsTCP("localhost",6667);
|
||||
#endif //PHYSICS_UDP
|
||||
|
||||
testSharedMemory(sm);
|
||||
}
|
||||
#endif
|
||||
|
67
test/clsocket/EchoServer.cpp
Normal file
67
test/clsocket/EchoServer.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
#include "PassiveSocket.h" // Include header for active socket object definition
|
||||
|
||||
#define MAX_PACKET 4096
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CPassiveSocket socket;
|
||||
CActiveSocket *pClient = NULL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize our socket object
|
||||
//--------------------------------------------------------------------------
|
||||
socket.Initialize();
|
||||
|
||||
socket.Listen("localhost", 6667);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((pClient = socket.Accept()) != NULL)
|
||||
{
|
||||
int clientPort = socket.GetClientPort();
|
||||
printf("connected from %s:%d\n", socket.GetClientAddr(),clientPort);
|
||||
//----------------------------------------------------------------------
|
||||
// Receive request from the client.
|
||||
//----------------------------------------------------------------------
|
||||
while (1)
|
||||
{
|
||||
//printf("try receive\n");
|
||||
bool receivedData = false;
|
||||
int recBytes = 0;
|
||||
recBytes = pClient->Receive(MAX_PACKET);
|
||||
if (recBytes)
|
||||
{
|
||||
char* msg = (char*) pClient->GetData();
|
||||
msg[recBytes]=0;
|
||||
printf("received message [%s]\n",msg);
|
||||
//------------------------------------------------------------------
|
||||
// Send response to client and close connection to the client.
|
||||
//------------------------------------------------------------------
|
||||
pClient->Send( pClient->GetData(), pClient->GetBytesReceived() );
|
||||
receivedData = true;
|
||||
if (strncmp(msg,"stop",4)==0)
|
||||
{
|
||||
printf("Stop request received\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!receivedData)
|
||||
{
|
||||
printf("Didn't receive data.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Disconnecting client.\n");
|
||||
pClient->Close();
|
||||
delete pClient;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Receive request from the client.
|
||||
//-----------------------------------------------------------------------------
|
||||
socket.Close();
|
||||
|
||||
return 1;
|
||||
}
|
58
test/clsocket/QueryDayTime.cpp
Normal file
58
test/clsocket/QueryDayTime.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "ActiveSocket.h" // Include header for active socket object definition
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CActiveSocket socket; // Instantiate active socket object (defaults to TCP).
|
||||
char time[50];
|
||||
|
||||
memset(&time, 0, 50);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize our socket object
|
||||
//--------------------------------------------------------------------------
|
||||
socket.Initialize();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create a connection to the time server so that data can be sent
|
||||
// and received.
|
||||
//--------------------------------------------------------------------------
|
||||
// if (socket.Open("time-C.timefreq.bldrdoc.gov", 13))
|
||||
if (socket.Open("192.168.86.196", 6667))
|
||||
{
|
||||
for (int i=0;i<100;i++)
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Send a requtest the server requesting the current time.
|
||||
//----------------------------------------------------------------------
|
||||
char data[1024];
|
||||
sprintf(data,"%s %d","Hello",i);
|
||||
int len = strlen(data);
|
||||
data[len]=0;
|
||||
printf("Sending [%s]\n",data);
|
||||
len++;
|
||||
if (socket.Send((const uint8 *)data, len))
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Receive response from the server.
|
||||
//----------------------------------------------------------------------
|
||||
int rec = socket.Receive(len);
|
||||
if (rec)
|
||||
{
|
||||
uint8* data = socket.GetData();
|
||||
memcpy(&time, data, len);
|
||||
printf("Received: [%s]\n", time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Close the connection.
|
||||
//----------------------------------------------------------------------
|
||||
socket.Close();
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
101
test/clsocket/RecvAsync.cpp
Normal file
101
test/clsocket/RecvAsync.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include <pthread.h>
|
||||
#include "PassiveSocket.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
|
||||
// usually defined with #include <unistd.h>
|
||||
static void sleep( unsigned int seconds )
|
||||
{
|
||||
Sleep( seconds * 1000 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAX_PACKET 4096
|
||||
#define TEST_PACKET "Test Packet"
|
||||
|
||||
struct thread_data
|
||||
{
|
||||
const char *pszServerAddr;
|
||||
short int nPort;
|
||||
int nNumBytesToReceive;
|
||||
int nTotalPayloadSize;
|
||||
};
|
||||
|
||||
|
||||
void *CreateTCPEchoServer(void *param)
|
||||
{
|
||||
CPassiveSocket socket;
|
||||
CActiveSocket *pClient = NULL;
|
||||
struct thread_data *pData = (struct thread_data *)param;
|
||||
int nBytesReceived = 0;
|
||||
|
||||
socket.Initialize();
|
||||
socket.Listen(pData->pszServerAddr, pData->nPort);
|
||||
|
||||
if ((pClient = socket.Accept()) != NULL)
|
||||
{
|
||||
while (nBytesReceived != pData->nTotalPayloadSize)
|
||||
{
|
||||
if (nBytesReceived += pClient->Receive(pData->nNumBytesToReceive))
|
||||
{
|
||||
pClient->Send((const uint8 *)pClient->GetData(), pClient->GetBytesReceived());
|
||||
}
|
||||
}
|
||||
|
||||
sleep(100);
|
||||
|
||||
delete pClient;
|
||||
}
|
||||
|
||||
socket.Close();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pthread_t threadId;
|
||||
struct thread_data thData;
|
||||
CActiveSocket client;
|
||||
char result[1024];
|
||||
|
||||
thData.pszServerAddr = "127.0.0.1";
|
||||
thData.nPort = 6789;
|
||||
thData.nNumBytesToReceive = 1;
|
||||
thData.nTotalPayloadSize = (int)strlen(TEST_PACKET);
|
||||
|
||||
pthread_create(&threadId, 0, CreateTCPEchoServer, &thData);
|
||||
sleep(1); // allow a second for the thread to create and listen
|
||||
|
||||
client.Initialize();
|
||||
client.SetNonblocking();
|
||||
|
||||
if (client.Open("127.0.0.1", 6789))
|
||||
{
|
||||
if (client.Send((uint8 *)TEST_PACKET, strlen(TEST_PACKET)))
|
||||
{
|
||||
int numBytes = -1;
|
||||
int bytesReceived = 0;
|
||||
|
||||
client.Select();
|
||||
|
||||
while (bytesReceived != strlen(TEST_PACKET))
|
||||
{
|
||||
numBytes = client.Receive(MAX_PACKET);
|
||||
|
||||
if (numBytes > 0)
|
||||
{
|
||||
bytesReceived += numBytes;
|
||||
memset(result, 0, 1024);
|
||||
memcpy(result, client.GetData(), numBytes);
|
||||
printf("received %d bytes: '%s'\n", numBytes, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Received %d bytes\n", numBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
test/clsocket/premake4.lua
Normal file
56
test/clsocket/premake4.lua
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
project ("Test_clsocket_EchoServer")
|
||||
|
||||
language "C++"
|
||||
|
||||
kind "ConsoleApp"
|
||||
|
||||
includedirs {"../../examples/ThirdPartyLibs/clsocket/src"}
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
links {"clsocket"}
|
||||
|
||||
files {
|
||||
"EchoServer.cpp",
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
project ("Test_clsocket_QueryDayTime")
|
||||
|
||||
language "C++"
|
||||
|
||||
kind "ConsoleApp"
|
||||
|
||||
includedirs {"../../examples/ThirdPartyLibs/clsocket/src"}
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
links {"clsocket"}
|
||||
|
||||
files {
|
||||
"QueryDayTime.cpp",
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user