initial checkin

This commit is contained in:
2024-08-01 17:19:14 -05:00
commit f6dbf0ccae
9 changed files with 882 additions and 0 deletions

38
ReceiveUDP.sln Normal file
View File

@@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34511.84
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReceiveUDP", "ReceiveUDP\ReceiveUDP.vcxproj", "{29652104-EA90-44DA-964C-F8D073D67A3D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadTest", "ThreadTest\ThreadTest.vcxproj", "{4BC4F1E9-6288-453C-B752-DC21E331B314}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{29652104-EA90-44DA-964C-F8D073D67A3D}.Debug|Win32.ActiveCfg = Debug|Win32
{29652104-EA90-44DA-964C-F8D073D67A3D}.Debug|Win32.Build.0 = Debug|Win32
{29652104-EA90-44DA-964C-F8D073D67A3D}.Debug|x64.ActiveCfg = Debug|x64
{29652104-EA90-44DA-964C-F8D073D67A3D}.Debug|x64.Build.0 = Debug|x64
{29652104-EA90-44DA-964C-F8D073D67A3D}.Release|Win32.ActiveCfg = Release|Win32
{29652104-EA90-44DA-964C-F8D073D67A3D}.Release|Win32.Build.0 = Release|Win32
{29652104-EA90-44DA-964C-F8D073D67A3D}.Release|x64.ActiveCfg = Release|x64
{29652104-EA90-44DA-964C-F8D073D67A3D}.Release|x64.Build.0 = Release|x64
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Debug|Win32.ActiveCfg = Debug|Win32
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Debug|Win32.Build.0 = Debug|Win32
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Debug|x64.ActiveCfg = Debug|x64
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Debug|x64.Build.0 = Debug|x64
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Release|Win32.ActiveCfg = Release|Win32
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Release|Win32.Build.0 = Release|Win32
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Release|x64.ActiveCfg = Release|x64
{4BC4F1E9-6288-453C-B752-DC21E331B314}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

40
ReceiveUDP/ReadMe.txt Normal file
View File

@@ -0,0 +1,40 @@
========================================================================
CONSOLE APPLICATION : ReceiveUDP Project Overview
========================================================================
AppWizard has created this ReceiveUDP application for you.
This file contains a summary of what you will find in each of the files that
make up your ReceiveUDP application.
ReceiveUDP.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
ReceiveUDP.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
ReceiveUDP.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named ReceiveUDP.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

326
ReceiveUDP/ReceiveUDP.cpp Normal file
View File

@@ -0,0 +1,326 @@
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iphlpapi.h> // For interface information
#include <string> // Include <string> for std::wstring
#include <stdio.h>
#include <algorithm> // all_of
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "IPHLPAPI.lib")
static const float progver = 0.1f;
static const char * byWho = "Smartware Computing";
static char RecvBuf[32768];
static int BufLen = 32767;
static char progname[255];
static volatile bool running; /// for the control-c handler to exit gracefully
static IP_ADAPTER_ADDRESSES *adapterAddresses = NULL;
typedef struct {
char *network;
int ipV;
unsigned short port;
} ProgOptions_T;
ProgOptions_T options = {
"", // user has to pick an interface
4, // Unspecified IPv
23725 // Wattwatcher
};
bool consoleHandler(int signal) {
if ( signal == CTRL_C_EVENT || signal == CTRL_BREAK_EVENT ) {
printf("User requested program exit with ctrl-c or ctrl-break.\n");
running = false;
return true;
} else {
printf("Unexpected console handler: %d\n", signal);
}
return false;
}
bool is_digits(const std::wstring &str) {
if ( str.length() == 0 ) return false;
return std::all_of(str.begin(), str.end(), ::isdigit); // C++11
}
///
/// Show the user a list of the available network interfaces
///
bool getInterfaces() {
ULONG bufferSize = 0;
GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize); // First call gets the bufferSize needed
adapterAddresses = new IP_ADAPTER_ADDRESSES[bufferSize];
if ( GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, adapterAddresses, &bufferSize) == NO_ERROR ) {
return true;
} else {
std::wcout << L"***** ERROR - Can't get the interfaces" << std::endl;
return false;
}
}
void listInterfaces() {
std::wcout << L" Available network interfaces:" << std::endl;
int ifNum = 1;
for ( IP_ADAPTER_ADDRESSES *adapter = adapterAddresses; adapter; adapter = adapter->Next ) {
std::wcout << " " << std::right << std::setw(2) << ifNum++ << L": " << std::left << std::setw(40) << adapter->FriendlyName << L" (" << adapter->Description << L")" << std::endl;
}
}
void clearInterfaces() {
delete[] adapterAddresses;
}
///
/// Let the user choose an interface
///
/// a pointer to the adapter
///
IP_ADAPTER_ADDRESSES *getInterface(std::wstring * userChoice = NULL) {
std::wstring selectedInterface; // Use std::wstring for wide strings
if ( *userChoice == L"" ) {
listInterfaces();
std::wcout << L" Select by number or partial name: ";
std::getline(std::wcin, selectedInterface);
userChoice = &selectedInterface;
} else {
std::wstring &userString = *userChoice;
userString.erase(std::remove(userString.begin(), userString.end(), L'"'), userString.end());
}
if ( userChoice->length() == 0 )
return NULL;
bool isNum = is_digits(*userChoice);
int userNum = 0; // no match
if ( isNum ) {
size_t pos = 0;
userNum = std::stoi(*userChoice, &pos);
}
int ifNum = 1;
for ( IP_ADAPTER_ADDRESSES *adapter = adapterAddresses; adapter; adapter = adapter->Next ) {
if (( isNum && ifNum == userNum )
|| (!isNum && wcsstr((wchar_t *)adapter->FriendlyName, userChoice->c_str()))) {
std::wcout << L" Chosen:" << std::endl;
std::wcout << L" " << std::right << std::setw(2) << ifNum++ << L": " << std::left << std::setw(40) << adapter->FriendlyName << L" (" << adapter->Description << L")" << std::endl;
return adapter;
}
}
return NULL;
}
void GetProgName(char *argv0) {
char *p = strrchr(argv0, '\\');
if ( p )
strcpy_s(progname, 255, p + 1);
else
strcpy_s(progname, 255, argv0);
p = strstr(progname, ".exe");
if ( p ) {
*p = '\0';
}
}
int GetProgOptions(int argc, char *argv[], ProgOptions_T *options) {
for ( int i = 1; i < argc; i++ ) {
if ( 0 == strncmp(argv[i], "-IF=", 4) ) { // -IF=<network interface number or name>
options->network = argv[i] + 4;
} else if ( 0 == strncmp(argv[i], "-IPv", 4) ) { // -IPv<version> ; -IPv4, -IPv6
options->ipV = atoi(argv[i] + 4);
} else if ( 0 == strncmp(argv[i], "-Port=", 6) ) { // -port=<port>
options->port = atoi(argv[i] + 6);
} else {
std::cout << "***** ERROR, option not recognized: " << argv[i] << std::endl;
return false;
}
}
return true;
}
// convert string to wide string
//
inline std::wstring convert(const std::string &as) {
if ( as.empty() )
return std::wstring();
size_t reqLength = ::MultiByteToWideChar(CP_UTF8, 0, as.c_str(), (int)as.length(), 0, 0);
std::wstring ret(reqLength, L'\0'); // construct new string of required length
::MultiByteToWideChar(CP_UTF8, 0, as.c_str(), (int)as.length(), &ret[0], (int)ret.length());
return ret; // return new string ( compiler should optimize this away )
}
int main(int argc, char *argv[]) {
int iResult = 0;
if ( !getInterfaces() ) {
return 1;
}
GetProgName(argv[0]);
if ( !GetProgOptions(argc, argv, &options) ) {
printf("\n\n%-60s v%3.1f by %s\n\n", progname, progver, byWho);
printf("Usage:\n %s [-IF=<name>] [-IPv<version>] [-Port=<portnum>], ctrl-c to exit.\n\n", progname);
printf(" <name> is the interface name or number as shown, default: '%s'\n", options.network);
printf(" <version> is the IP version; '0' for unspecified, or '4' or '6', default: 'IPv%u'\n", options.ipV);
printf(" <portnum> is the port number to listen to. default: %u\n", options.port);
printf("\n");
listInterfaces();
exit(1);
}
std::wstring optNet = convert(options.network);
IP_ADAPTER_ADDRESSES * interface = getInterface(&optNet);
if ( interface != NULL ) {
static char ref[255]; // icky hack
wcstombs(ref, interface->FriendlyName, 255);
options.network = ref;
} else {
std::wcout << L"***** ERROR - no (or invalid) interface chosen" << std::endl;
exit(1);
}
if ( options.ipV != 0 && options.ipV != 4 && options.ipV != 6 ) {
std::wcout << L"***** ERROR - Invalid IP version chosen" << std::endl;
exit(1);
}
std::cout << "Interface: " << options.network << std::endl;
std::cout << " Port: " << options.port << std::endl;
std::cout << " IPv: " << options.ipV << std::endl;
running = true;
if ( !SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(consoleHandler), TRUE) ) {
printf("***** ERROR ***** Could not set control handler.\n");
return 1;
}
int IPFamily = AF_INET;
switch ( options.ipV ) {
default:
IPFamily = AF_UNSPEC;
break;
case 4:
IPFamily = AF_INET;
break;
case 6:
IPFamily = AF_INET6;
break;
}
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in6 RecvAddr = { 0 };
sockaddr_in6 SenderAddr = { 0 };
int SenderAddrSize = sizeof(SenderAddr);
LARGE_INTEGER StartingTime = { 0 };
LARGE_INTEGER EndingTime = { 0 };
LARGE_INTEGER ElapsedMicroseconds = { 0 };
LARGE_INTEGER Frequency{ 0 };
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&StartingTime);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if ( iResult != NO_ERROR ) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(IPFamily, SOCK_DGRAM, IPPROTO_UDP);
if ( RecvSocket == INVALID_SOCKET ) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin6_family = IPFamily;
RecvAddr.sin6_port = htons(options.port);
RecvAddr.sin6_addr = in6addr_any; // .in6addr_any = INADDR_ANY;
//inet_pton(AF_INET6, "ff02::fb", (void *)&RecvAddr.sin6_addr.s6_addr);
//int on = 1;
//if ( RecvAddr.sin6_family == AF_INET6 ) {
// setsockopt(RecvSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on, sizeof(on));
//}
iResult = bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
if ( iResult != 0 ) {
wprintf(L"***** bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams on port %d... (hit <esc> to quit, or ctrl-c)\n", options.port);
DWORD timeout_ms = 20;
setsockopt(RecvSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_ms, sizeof(timeout_ms));
while ( running ) {
if ( _kbhit() ) {
if (_getch() == '\x1B' )
break;
}
iResult = recvfrom(RecvSocket,
RecvBuf, BufLen,
0, (SOCKADDR *)&SenderAddr,
&SenderAddrSize
);
if ( iResult == SOCKET_ERROR ) {
int lastErr = WSAGetLastError();
if ( lastErr != WSAETIMEDOUT ) {
wprintf(L"recvfrom failed with error %d\n", lastErr);
break;
}
} else {
// Activity to be timed
QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
// We now have the elapsed number of ticks, along with the
// number of ticks-per-second. We use these values
// to convert to the number of elapsed microseconds.
// To guard against loss-of-precision, we convert
// to microseconds *before* dividing by ticks-per-second.
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
float delta = (float)ElapsedMicroseconds.QuadPart / 1000000;
RecvBuf[iResult] = '\0';
printf("Rx[%5.3f]: %s\n", delta, RecvBuf);
StartingTime = EndingTime;
}
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
iResult = closesocket(RecvSocket);
if ( iResult == SOCKET_ERROR ) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
//wprintf(L"Exiting.\n");
WSACleanup();
clearInterfaces();
return 0;
}

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{29652104-EA90-44DA-964C-F8D073D67A3D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ReceiveUDP</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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 Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<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>
</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>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ReceiveUDP.cpp" />
<ClCompile Include="stdafx.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

8
ReceiveUDP/stdafx.cpp Normal file
View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ReceiveUDP.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

15
ReceiveUDP/stdafx.h Normal file
View File

@@ -0,0 +1,15 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here

8
ReceiveUDP/targetver.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

153
ThreadTest/ThreadTest.cpp Normal file
View File

@@ -0,0 +1,153 @@
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define MAX_THREADS 3
#define BUF_SIZE 255
DWORD WINAPI MyThreadFunction(LPVOID lpParam);
void ErrorHandler(LPCTSTR lpszFunction);
// Sample custom data structure for threads to use.
// This is passed by void pointer so it can be any data type
// that can be passed using a single void pointer (LPVOID).
typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA;
bool running = true;
int _tmain() {
PMYDATA pDataArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS];
// Create MAX_THREADS worker threads.
for ( int i = 0; i < MAX_THREADS; i++ ) {
// Allocate memory for thread data.
pDataArray[i] = (PMYDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(MYDATA));
if ( pDataArray[i] == NULL ) {
// If the array allocation fails, the system is out of memory
// so there is no point in trying to print an error message.
// Just terminate execution.
ExitProcess(2);
}
// Generate unique data for each thread to work with.
pDataArray[i]->val1 = i;
pDataArray[i]->val2 = i + 100;
// Create the thread to begin execution on its own.
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
pDataArray[i], // argument to thread function
0, // use default creation flags
&dwThreadIdArray[i]); // returns the thread identifier
// Check the return value for success.
// If CreateThread fails, terminate execution.
// This will automatically clean up threads and memory.
if ( hThreadArray[i] == NULL ) {
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
} // End of main thread creation loop.
// Wait until all threads have terminated.
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
// Close all thread handles and free memory allocations.
for ( int i = 0; i < MAX_THREADS; i++ ) {
CloseHandle(hThreadArray[i]);
if ( pDataArray[i] != NULL ) {
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL; // Ensure address is not reused.
}
}
return 0;
}
DWORD WINAPI MyThreadFunction(LPVOID lpParam) {
HANDLE hStdout;
PMYDATA pDataArray;
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;
// Make sure there is a console to receive output results.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if ( hStdout == INVALID_HANDLE_VALUE )
return 1;
int counter = 0;
while (running) {
// Cast the parameter to the correct data type.
// The pointer is known to be valid because
// it was checked for NULL before the thread was created.
pDataArray = (PMYDATA)lpParam;
// Print the parameter values using thread-safe functions.
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d, [%d]\n"),
pDataArray->val1, pDataArray->val2, counter++);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
Sleep(1000 + 1000 * pDataArray->val1 );
if ( counter > 5 )
break;
}
return 0;
}
void ErrorHandler(LPCTSTR lpszFunction) {
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{4bc4f1e9-6288-453c-b752-dc21e331b314}</ProjectGuid>
<RootNamespace>ThreadTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</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" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ThreadTest.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>