// ConsoleApplication.cpp : This file contains the 'main' function. Program
// execution begins and ends there.
//
//TODO from dcmtk
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <winsock2.h> /* for SO_EXCLUSIVEADDRUSE */
#include <ws2tcpip.h> /* for socklen_t */
#include <sstream>
#include <string>
#include <iostream>
#ifdef HAVE_IOS
#include <ios>
#endif
#include <fstream>
#include <iomanip>
// For standard STREAMS library: preference for standard stringstream
#if defined(HAVE_SSTREAM)
#include <sstream>
#define USE_STRINGSTREAM
#elif defined(HAVE_STRSTREAM)
#include <strstream>
#else
#endif
//begin
// Definition of type OFBool
#ifdef _WIN32
static char **command_argv = NULL;
static int command_argc = 0;
#endif
typedef bool OFBool;
#define OFTrue true
#define OFFalse false
#define OFString std::string
// define STD_NAMESPACE to std:: if the standard namespace exists
#ifndef STD_NAMESPACE
#ifdef HAVE_STD_NAMESPACE
#define STD_NAMESPACE std::
#else
#define STD_NAMESPACE
#endif
#endif
typedef STD_NAMESPACE stringstream OFStringStream;
typedef STD_NAMESPACE ostringstream OFOStringStream;
typedef STD_NAMESPACE istringstream OFIStringStream;
#define OFStringStream_ends ""
#define OFconst_cast(x, y) (const_cast<x>(y))
#define OFreinterpret_cast(x, y) (reinterpret_cast<x>(y))
#define OFstatic_cast(x, y) (static_cast<x>(y))
#ifdef HAVE_STL_STRING
#define OFSTRINGSTREAM_GETOFSTRING(oss, strng) OFString strng((oss).str());
#else
#define OFSTRINGSTREAM_GETOFSTRING(oss, strng) \
STD_NAMESPACE string strng##__((oss).str()); \
OFString strng(strng##__.c_str(), strng##__.length());
#endif
#pragma comment(lib, "Ws2_32.lib")
//#define makeDcmnetCondition(A, B, C) makeOFCondition(OFM_dcmnet, (A), (B),
//(C))
/** this enumeration describes the return status of an operation.
*/
enum OFStatus {
/// no error, operation has completed successfully
OF_ok,
/// operation has not completed successfully
OF_error,
/// application failure
OF_failure
};
static bool ReceiveTransportConnectionTCP(int command_argc,
char **command_argv) {
//#elif defined(_WIN32)
//initializeNetworkTCP
#ifdef _WIN32
SOCKET sock;
#else
int sock;
#endif
WSADATA wsa;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
//{
struct linger sockarg;
int reuse = 1;
(void)memset(&sockarg, 0, sizeof(sockarg));
{
//#ifdef HAVE_DECLARATION_SOCKLEN_T
socklen_t length;
//#elif !defined(HAVE_PROTOTYPE_ACCEPT) || defined(HAVE_INTP_ACCEPT)
// int length;
//#else
// size_t length;
//#endif
struct sockaddr_in server;
/* Create socket for Internet type communication */
//(*key)->networkSpecific.TCP.port = *(int *)parameter;
//(*key)->networkSpecific.TCP.listenSocket =
// sock = socket(AF_INET, SOCK_STREAM, 0);
//(*key) ->networkSpecific.TCP.listenSocket;
if (sock == INVALID_SOCKET)
{
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
reuse = 1;
#ifdef _WIN32
if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&reuse,
sizeof(reuse)) < 0)
#else
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse,
sizeof(reuse)) < 0)
#endif
{
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
/* Name socket using wildcards */
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = 103;
//(unsigned short)htons((*key)->networkSpecific.TCP.port);
if (bind(sock, (struct sockaddr *)&server, sizeof(server))) {
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
/* Find out assigned port number and print it out */
length = sizeof(server);
if (getsockname(sock, (struct sockaddr *)&server, &length)) {
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
sockarg.l_onoff = 0;
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&sockarg,
sizeof(sockarg)) < 0) {
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
/* Listen on the socket */
#define PRV_LISTENBACKLOG 50
if (listen(sock, PRV_LISTENBACKLOG) < 0) {
OFString msg = "TCP Initialization Error: ";
//msg += OFStandard::getLastNetworkErrorCode().message();
//return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
return false;
}
}
//(*key)->networkSpecific.TCP.tLayer = new DcmTransportLayer();
//(*key)->networkSpecific.TCP.tLayerOwned = 1;
//if (NULL == (*key)->networkSpecific.TCP.tLayer) {
// return makeDcmnetCondition(DULC_TCPINITERROR, OF_error,
// "Cannot initialize DcmTransportLayer");
//}
//}
//= dcmExternalSocketHandle.get();
bool shouldFork = true;
if (shouldFork /*&& (command_argc > 0) && command_argv*/) {
// win32 code to create new child process
HANDLE childSocketHandle;
HANDLE hChildStdInRead;
HANDLE hChildStdInWrite;
HANDLE hChildStdInWriteDup;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
// prepare the command line
OFString cmdLine = command_argv[0];
//"D:\\code\\ConsoleApp\\ConsoleApplication\\Debug\\ConsoleApplication.exe";
cmdLine += " --forked-child";
for (int i = 1; i < command_argc; ++i) {
/* copy each argv value and surround it with double quotes
* to keep option values containing a space glued together
*/
cmdLine += " \"";
cmdLine += command_argv[i];
/* if last character in argument value is a backslash, escape it
* since otherwise it would escape the quote appended in the following
* step, i.e. make sure that something like '\my\dir\' does not become
* '"\my\dir\"' but instead ends up as '"\my\dir\\"' (single quotes for
* demonstration purposes). Make sure nobody passes a zero length string.
*/
size_t len = strlen(command_argv[i]);
if ((len > 0) && (command_argv[i][len - 1] == '\\')) {
cmdLine += "\\";
}
cmdLine += "\"";
}
std::cout << cmdLine << "\n";
// create anonymous pipe
if (!CreatePipe(&hChildStdInRead, &hChildStdInWrite, &sa, 0)) {
OFOStringStream stream;
stream
<< "Multi-Process Error: Creating anonymous pipe failed with error "
"code "
<< GetLastError() << OFStringStream_ends;
OFSTRINGSTREAM_GETOFSTRING(stream, msg);
// return makeDcmnetCondition(DULC_CANNOTFORK, OF_error, msg.c_str());
return false;
}
// create duplicate of write end handle of pipe
if (!DuplicateHandle(GetCurrentProcess(), hChildStdInWrite,
GetCurrentProcess(), &hChildStdInWriteDup, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
// return makeDcmnetCondition(DULC_CANNOTFORK, OF_error, "Multi-Process
// Error: Duplicating handle failed");
return false;
}
// destroy original write end handle of pipe
CloseHandle(hChildStdInWrite);
// we need a STARTUPINFO and a PROCESS_INFORMATION structure for
// CreateProcess.
STARTUPINFOA si;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
// prepare startup info for child process:
// the child uses the same stdout and stderr as the parent, but
// stdin is the read end of our anonymous pipe.
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
si.hStdInput = hChildStdInRead;
// create child process.
if (!CreateProcessA(NULL, OFconst_cast(char *, cmdLine.c_str()), NULL, NULL,
TRUE, 0, NULL, NULL, &si, &pi)) {
OFOStringStream stream;
stream << "Multi-Process Error: Creating process failed with error code "
<< GetLastError() << OFStringStream_ends;
OFSTRINGSTREAM_GETOFSTRING(stream, msg)
// return makeDcmnetCondition(DULC_CANNOTFORK, OF_error, msg.c_str());
return false;
} else {
// call OpenProcess to retrieve the REAL process handle. using
// GetCurrentProcess() only returns a pseudo handle which may not
// allow DuplicateHandle to create the child process socket with
// sufficient permissions on certain versions of Windows.
HANDLE hParentProcessHandle =
OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
if (hParentProcessHandle == NULL) {
// unable to get process handle...
// ...this should really never happen as we are opening the current
// process.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle((HANDLE)sock);
OFOStringStream stream;
stream << "Multi-Process Error: Opening process to get real process "
"handle failed with error code "
<< GetLastError() << OFStringStream_ends;
OFSTRINGSTREAM_GETOFSTRING(stream, msg)
// return makeDcmnetCondition(DULC_CANNOTFORK, OF_error, msg.c_str());
return false;
}
// PROCESS_INFORMATION pi now contains various handles for the new
// process. Now that we have a handle to the new process, we can duplicate
// the socket handle into the new child process.
if (DuplicateHandle(hParentProcessHandle, (HANDLE)sock, pi.hProcess,
&childSocketHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
// close handles in PROCESS_INFORMATION structure
// and our local copy of the socket handle.
CloseHandle(hParentProcessHandle);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
closesocket(sock);
// send number of socket handle in child process over anonymous pipe
DWORD bytesWritten;
char buf[30];
// we pass the socket handle as a 64-bit unsigned integer, which should
// work for 32 and 64 bit Windows
sprintf(buf, "%llu",
OFreinterpret_cast(unsigned __int64, childSocketHandle));
if (!WriteFile(hChildStdInWriteDup, buf,
OFstatic_cast(DWORD, strlen(buf) + 1), &bytesWritten,
NULL)) {
CloseHandle(hChildStdInWriteDup);
// return makeDcmnetCondition( DULC_CANNOTFORK,
// OF_error,"Multi-Process Error: Writing to anonymous pipe failed");
return false;
}
// return OF_ok status code DULC_FORKEDCHILD with descriptive text
OFOStringStream stream;
stream << "New child process started with pid "
<< OFstatic_cast(int, pi.dwProcessId) << ", socketHandle "
<< OFstatic_cast(int,
OFreinterpret_cast(size_t, childSocketHandle))
<< OFStringStream_ends;
OFSTRINGSTREAM_GETOFSTRING(stream, msg);
// return makeDcmnetCondition(DULC_FORKEDCHILD, OF_ok, msg.c_str());
std::cout << "New child process started with pid=" << pi.dwProcessId
<< "\n";
return true;
} else {
// unable to duplicate handle. Close handles nevertheless
// to avoid resource leak.
CloseHandle(hParentProcessHandle);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
// return makeDcmnetCondition(DULC_CANNOTFORK, OF_error, "Multi-Process
// Error: Duplicating socket handle failed");
return false;
}
}
}
return true;
}
//#endif
int main(int command_argc, char **command_argv) {
std::cout << "Hello World!\n";
bool need_fork = true;
for (int i = 1; i < command_argc; ++i) {
if (std::string(command_argv[i]) == "--forked-child") {
need_fork = false;
}
}
if (need_fork) {
bool bret = ReceiveTransportConnectionTCP(command_argc, command_argv);
bret;
std::cout << "forked-child input a number\n";
int i = 0;
std::cin >> i;
std::cout << "end\n";
}
std::cout << "input a number\n";
int i = 0;
std::cin >> i;
std::cout << "end\n";
}
Windows版本fock(TODO)
最新推荐文章于 2024-03-29 11:50:14 发布