added ping-pong networking example

Signed-off-by: Jak Barnes <contact@jakbarnes.co.uk>
This commit is contained in:
Jak Barnes 2019-02-16 00:44:30 +00:00
parent 85967c9f36
commit bb01a49398
7 changed files with 1995 additions and 1569 deletions

View File

@ -1,74 +1,102 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [core] example - Basic window * raylib [core] example - Basic window
* *
* Welcome to raylib! * Welcome to raylib!
* *
* To test examples, just press F6 and execute raylib_compile_execute script * To test examples, just press F6 and execute raylib_compile_execute script
* Note that compiled executable is placed in the same folder as .c file * Note that compiled executable is placed in the same folder as .c file
* *
* You can find all basic examples on C:\raylib\raylib\examples folder or * You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com * raylib official webpage: www.raylib.com
* *
* Enjoy using raylib. :) * Enjoy using raylib. :)
* *
* This example has been created using raylib 1.0 (www.raylib.com) * This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h
* *for details)
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5) *
* * Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
********************************************************************************************/ *
********************************************************************************************/
#include "raylib.h" #include "raylib.h"
int main() int main()
{ {
// Initialization // Setup
//-------------------------------------------------------------------------------------- int screenWidth = 800;
int screenWidth = 800;
int screenHeight = 450; int screenHeight = 450;
InitWindow(
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); screenWidth, screenHeight, "raylib [network] example - ping pong");
SetTargetFPS(60); SetTargetFPS(60);
//--------------------------------------------------------------------------------------
const int port = 5000; // Networking
Address* address = &(struct Address) { 127, 0, 0, 1, port }; TCPSocket server;
Address* sender = NULL; TCPSocket client;
int handle = -1; TCPSocket connection;
const char data[] = "Ping!"; ResetSocket(&server);
ResetSocket(&client);
ResetSocket(&connection);
// Socket creation InitNetwork();
InitializeSockets(); CreateTCPListenServer(&server, "127.0.0.1", "3490");
handle = CreateUDPSocket(); CreateTCPClient(&client, "127.0.0.1", "3490");
OpenSocket(handle, port);
SendData(handle, address, data, sizeof(data)); // Timer
float elapsed = 0.0f, delay = 1.0f; // ms
bool ping = false, pong = false;
char recvBuffer[512];
memset(&recvBuffer, 0, 8);
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) {
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw // Draw
//----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
// Clear
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); // A valid connection will != -1
if (!connection.ready) {
AcceptIncomingConnections(&connection, server.sockfd);
ping = true;
}
// Connected
if (connection.ready) {
int bytesRecv = ReceiveTCP(connection.sockfd, recvBuffer, 5);
if (bytesRecv > 0) {
if (strcmp(recvBuffer, "Ping!") == 0) {
pong = true;
printf("Ping!\n");
}
if (strcmp(recvBuffer, "Pong!") == 0) {
ping = true;
printf("Pong!\n");
}
}
elapsed += GetFrameTime();
if (elapsed > delay) {
if (ping) {
ping = false;
SendTCP(client.sockfd, "Ping!", 5);
} else if (pong) {
pong = false;
SendTCP(client.sockfd, "Pong!", 5);
}
elapsed = 0.0f;
}
}
// End draw
EndDrawing(); EndDrawing();
//----------------------------------------------------------------------------------
} }
// De-Initialization // Cleanup
//-------------------------------------------------------------------------------------- CloseWindow();
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0; return 0;
} }

View File

@ -0,0 +1,54 @@
/*******************************************************************************************
*
* raylib [core] example - Basic window
*
* Welcome to raylib!
*
* To test examples, just press F6 and execute raylib_compile_execute script
* Note that compiled executable is placed in the same folder as .c file
*
* You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com
*
* Enjoy using raylib. :)
*
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h
*for details)
*
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Setup
int screenWidth = 800;
int screenHeight = 450;
InitWindow(
screenWidth, screenHeight, "raylib [network] example - ping pong");
SetTargetFPS(60);
// Networking
InitNetwork();
ResolveHost("www.raylib.com");
// Main game loop
while (!WindowShouldClose()) {
// Draw
BeginDrawing();
// Clear
ClearBackground(RAYWHITE);
// End draw
EndDrawing();
}
// Cleanup
CloseWindow();
return 0;
}

View File

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\examples\network\network_resolve_host.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\raylib\raylib.vcxproj">
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{A16D19CB-6AF4-4D17-8318-EABD8805247C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>networkpingpong</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<ProjectName>network_resolve_host</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_ping_pong", "exampl
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_basic_window", "examples\core_basic_window.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_basic_window", "examples\core_basic_window.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_interfaces", "examples\network_interfaces.vcxproj", "{A16D19CB-6AF4-4D17-8318-EABD8805247C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|x64 = Debug.DLL|x64 Debug.DLL|x64 = Debug.DLL|x64
@ -77,6 +79,22 @@ Global
{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.ActiveCfg = Release|Win32 {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x64.ActiveCfg = Release|Win32
{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.ActiveCfg = Release|Win32 {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.ActiveCfg = Release|Win32
{0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.Build.0 = Release|Win32 {0981CA98-E4A5-4DF1-987F-A41D09131EFC}.Release|x86.Build.0 = Release|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug.DLL|x64.ActiveCfg = Debug|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug.DLL|x64.Build.0 = Debug|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug.DLL|x86.ActiveCfg = Debug|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug.DLL|x86.Build.0 = Debug|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug|x64.ActiveCfg = Debug|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug|x64.Build.0 = Debug|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug|x86.ActiveCfg = Debug|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Debug|x86.Build.0 = Debug|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release.DLL|x64.ActiveCfg = Release|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release.DLL|x64.Build.0 = Release|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release.DLL|x86.ActiveCfg = Release|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release.DLL|x86.Build.0 = Release|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x64.ActiveCfg = Release|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x64.Build.0 = Release|x64
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.ActiveCfg = Release|Win32
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -85,6 +103,7 @@ Global
{B655E850-3322-42F7-941D-6AC18FD66CA1} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {B655E850-3322-42F7-941D-6AC18FD66CA1} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{56EB485C-00A9-459E-B758-2E86316EB7FD} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {56EB485C-00A9-459E-B758-2E86316EB7FD} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{0981CA98-E4A5-4DF1-987F-A41D09131EFC} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {0981CA98-E4A5-4DF1-987F-A41D09131EFC} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{A16D19CB-6AF4-4D17-8318-EABD8805247C} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

View File

@ -418,14 +418,12 @@ typedef struct VrStereoConfig {
int eyeViewportLeft[4]; // VR stereo rendering left eye viewport [x, y, w, h] int eyeViewportLeft[4]; // VR stereo rendering left eye viewport [x, y, w, h]
} VrStereoConfig; } VrStereoConfig;
// Address struct in the form a.b.c.d where [a, b, c, d] are >= 0 && <= 255 // TCP Stream socket
typedef struct Address { typedef struct TCPSocket {
unsigned char a; int sockfd;
unsigned char b; int server;
unsigned char c; bool ready;
unsigned char d; } TCPSocket;
short port;
} Address;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Enumerators Definition // Enumerators Definition
@ -1385,13 +1383,15 @@ RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set vol
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
// Network functions // Network functions
RLAPI bool InitializeSockets(void); RLAPI bool InitNetwork(void);
RLAPI void ShutdownSockets(void); RLAPI void CloseNetwork(void);
RLAPI int CreateUDPSocket(void); RLAPI void CreateTCPListenServer(TCPSocket* socket, const char* address, const int port);
RLAPI bool OpenSocket(int handle, unsigned short port); RLAPI void CreateTCPClient(TCPSocket* socket, const char* address, const char* port);
RLAPI bool SendData(int handle, const Address* destination, const void* data, int size); RLAPI void AcceptIncomingConnections(TCPSocket* sock, int sockfd);
RLAPI bool ReceiveData(int handle, Address* sender, void* data, int size); RLAPI int SendTCP(int sockfd, const char* data, int len);
RLAPI int AddressToInt(Address address); RLAPI int ReceiveTCP(int sockfd, const char* data, int len);
RLAPI void ResetSocket(TCPSocket* socket);
RLAPI void ResolveHost(const char* hostname);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -38,108 +38,238 @@
// Check if config flags have been externally provided on compilation line // Check if config flags have been externally provided on compilation line
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if !defined(EXTERNAL_CONFIG_FLAGS) #if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags # include "config.h" // Defines module configuration flags
#endif #endif
#include "sysnet.h"
#include "raylib.h" #include "raylib.h"
#include "sysnet.h"
bool InitializeSockets() #include <errno.h>
#include <stdlib.h>
bool InitNetwork()
{ {
#if PLATFORM == PLATFORM_WINDOWS #if PLATFORM == PLATFORM_WINDOWS
WSADATA WsaData; WSADATA wsaData;
return WSAStartup if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR) {
( TraceLog(LOG_INFO, "WinSock initialised.");
MAKEWORD(2, 2), return true;
&WsaData } else {
) == NO_ERROR; TraceLog(LOG_WARNING, "WinSock failed to initialise.");
return false;
}
#else #else
return true; return true;
#endif #endif
} }
void ShutdownSockets() void CloseNetwork()
{ {
#if PLATFORM == PLATFORM_WINDOWS #if PLATFORM == PLATFORM_WINDOWS
WSACleanup(); WSACleanup();
#endif #endif
} }
int CreateUDPSocket() void CreateTCPListenServer(TCPSocket* tcpsock, const char* address, const char* port)
{ {
int handle = socket(AF_INET, // Variables
SOCK_DGRAM, int status; // Status value to return (0) is success
IPPROTO_UDP); struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
struct addrinfo* results; // A pointer to the resulting address list
if (handle <= 0) // Set the hints
{ memset(&hints, 0, sizeof hints);
printf("failed to create socket\n"); hints.ai_family = AF_INET; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
return false; hints.ai_socktype = SOCK_STREAM; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
// Populate address information
status = getaddrinfo(address, // e.g. "www.example.com" or IP
port, // e.g. "http" or port number
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
&results // The struct to populate
);
// Did we succeed?
if (status == -1) {
TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", address, port, strerror(status));
} else {
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port);
} }
return handle; // Create our server socket
} int sockfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
bool OpenSocket(int handle, unsigned short port) // Bind it to the port we passed in to getaddrinfo():
{ status = bind(sockfd, results->ai_addr, results->ai_addrlen);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons((unsigned short)port);
if (bind(handle, (const struct sockaddr*)&address, sizeof( struct sockaddr_in)) < 0) // Did we succeed?
{ if (status == -1) {
printf("failed to bind socket\n"); TraceLog(LOG_WARNING, "Failed to get bind socket to port (%s): %s", port, strerror(errno));
return false; } else {
TraceLog(LOG_INFO, "Successfully bound %s to port (%s)", address, port);
} }
#if PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX // Listen on the bound port
status = listen(sockfd, 5);
int nonBlocking = 1; // Did we succeed?
if (fcntl(handle, F_SETFL, O_NONBLOCK, nonBlocking) == -1) if (status == -1) {
{ TraceLog(LOG_WARNING, "Failed to listen to socket: %s", strerror(errno));
printf("failed to set non-blocking\n"); } else {
return false; TraceLog(LOG_INFO, "Successfully started listen server.");
} }
#elif PLATFORM == PLATFORM_WINDOWS
DWORD nonBlocking = 1; DWORD nonBlocking = 1;
if (ioctlsocket(handle, FIONBIO, &nonBlocking) != 0) if (ioctlsocket(sockfd, FIONBIO, &nonBlocking) == -1) {
{ TraceLog(LOG_WARNING, "Failed to set socket to non-blocking.");
printf("failed to set non-blocking\n"); } else {
return false; TraceLog(LOG_INFO, "Successfully set socket to non-blocking.");
} }
#endif // Free the linked-list, we're not using it anymore
freeaddrinfo(results);
return true; // Finally, return our socket descriptor
tcpsock->sockfd = sockfd;
tcpsock->server = 1;
tcpsock->ready = true;
return;
} }
bool SendData(int handle, const Address* destination, const void* data, int size) void CreateTCPClient(TCPSocket* tcpsock, char* address, char* port)
{ {
int sent_bytes = sendto(handle, (const char*) data, size, 0, ( struct sockaddr*) &destination, sizeof(struct sockaddr_in)); int status;
if (sent_bytes != size) { int sockfd;
printf("failed to send packet\n"); struct addrinfo hints;
return false; struct addrinfo* results; // Will point to the results
memset(&hints, 0, sizeof hints); // Make sure the struct is empty
hints.ai_family = AF_UNSPEC; // Don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
// Get ready to connect
status = getaddrinfo(address, port, &hints, &results);
// Did we succeed?
if (status != 0) {
TraceLog(LOG_WARNING, "Failed to get address information: %s", strerror(errno));
} else {
TraceLog(LOG_INFO, "Successfully created TCP client on port (%s)", port);
}
// Create our socket
sockfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
// Did it succeed?
if (sockfd == -1) {
TraceLog(LOG_WARNING, "Failed to create socket: %s", strerror(errno));
} else {
TraceLog(LOG_INFO, "Successfully created socket");
}
// Connect to the server
status = connect(sockfd, results->ai_addr, results->ai_addrlen);
if (status == -1) {
TraceLog(LOG_WARNING, "Failed to connect to server %s:%s", address, port);
} else {
TraceLog(LOG_INFO, "Successfully connected to %s:%s", address, port);
}
freeaddrinfo(results);
// Finally, return our socket descriptor
tcpsock->sockfd = sockfd;
tcpsock->server = 0;
tcpsock->ready = true;
}
void AcceptIncomingConnections(TCPSocket* tcpsock, int sockfd)
{
struct sockaddr_storage their_addr;
socklen_t addr_size;
int new_fd;
addr_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr*) &their_addr, &addr_size);
if (new_fd == -1) {
TraceLog(LOG_DEBUG, "Failed to accept incoming connection: %s", strerror(errno));
} else {
tcpsock->sockfd = new_fd;
tcpsock->server = false;
tcpsock->ready = true;
TraceLog(LOG_INFO, "Successfully accepted a new connection.");
} }
} }
int ReceiveData(int handle, Address* sender, void* data, int size) int SendTCP(int sockfd, const char* data, int len)
{ {
#if PLATFORM == PLATFORM_WINDOWS int sentBytes = send(sockfd, data, len, 0);
typedef int socklen_t; if (sentBytes == -1) {
#endif TraceLog(LOG_WARNING, "Failed to send data: %s", strerror(errno));
} else {
while (true) { TraceLog(LOG_DEBUG, "Successfully sent %d bytes.", sentBytes);
socklen_t fromLength = sizeof(AddressToInt(*sender));
int bytes = recvfrom(handle, (char*) data, size, 0, (struct sockaddr*) &sender, &fromLength);
if (bytes <= 0) break;
return bytes;
} }
} }
int AddressToInt(Address address) int ReceiveTCP(int sockfd, const char* data, int len)
{ {
return (address.a << 24) | (address.b << 16) | (address.c << 8) | address.d; int receiveBytes = recv(sockfd, data, len, 0);
if (receiveBytes == -1) {
TraceLog(LOG_DEBUG, "Failed to receive data: %s", strerror(errno));
} else if (receiveBytes == 0) {
TraceLog(LOG_INFO, "Connection closed.");
} else {
TraceLog(LOG_DEBUG, "Successfully received %d bytes.", receiveBytes);
}
return receiveBytes;
}
void ResetSocket(TCPSocket* socket)
{
socket->ready = false;
socket->server = 0;
socket->sockfd = -1;
};
void ResolveHost(const char* hostname)
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
TraceLog(LOG_WARNING, "getaddrinfo: %s", strerror(status));
return 2;
}
TraceLog(LOG_INFO, "IP addresses for %s:", hostname);
for (p = res; p != NULL; p = p->ai_next) {
void* addr;
char* ipver;
// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in* ipv4 = (struct sockaddr_in*) p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*) p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
// convert the IP to a string and print it:
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
TraceLog(LOG_INFO, "%s: %s", ipver, ipstr);
}
freeaddrinfo(res); // free the linked list
} }

View File

@ -45,36 +45,58 @@
#define MMNOSOUND #define MMNOSOUND
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Platform specific network includes // Platform defines
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define PLATFORM_WINDOWS 1 #define PLATFORM_WINDOWS 1
#define PLATFORM_MAC 2 #define PLATFORM_UNIX 2
#define PLATFORM_UNIX 3
#if defined(_WIN32) #if defined(__WIN32__) || defined(WIN32)
#define PLATFORM PLATFORM_WINDOWS #define PLATFORM PLATFORM_WINDOWS
#elif defined(__APPLE__)
#define PLATFORM PLATFORM_MAC
#else #else
#define PLATFORM PLATFORM_UNIX #define PLATFORM PLATFORM_UNIX
#endif #endif
#if PLATFORM == PLATFORM_WINDOWS //----------------------------------------------------------------------------------
// #define _INC_WINDOWS // Platform specific network includes
// #define WIN32_LEAN_AND_MEAN //----------------------------------------------------------------------------------
// #include <minwindef.h>
#endif
#if PLATFORM == PLATFORM_WINDOWS #if PLATFORM_WINDOWS
#define __USE_W32_SOCKETS
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h> #include <winsock2.h>
#elif PLATFORM == PLATFORM_MAC || PLATFORM == PLATFORM_UNIX #include <ws2tcpip.h>
#include <iphlpapi.h>
#else /* UNIX */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif #include <net/if.h>
#include <netdb.h>
#endif /* WIN32 */
#if PLATFORM == PLATFORM_WINDOWS /* System-dependent definitions */
#pragma comment(lib, "wsock32.lib") #ifndef __USE_W32_SOCKETS
#define closesocket close
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif /* __USE_W32_SOCKETS */
#ifdef __USE_W32_SOCKETS
#define RNet_GetLastError WSAGetLastError
#define RNet_SetLastError WSASetLastError
#ifndef EINTR
#define EINTR WSAEINTR
#endif
#else
int RNet_GetLastError(void);
void RNet_SetLastError(int err);
#endif #endif