📄 syncserver.c
字号:
if (Data->ForceStop == YES) {
i = 0;
setsockopt(Data->ReceiveSocket,SOL_SOCKET,SO_DONTLINGER,(char *)&i,sizeof(i));
}
sprintf(s1,"%s Disconnected.",Data->RemoteAddress);
LogMessage(s1);
if (closesocket(Data->ReceiveSocket) != 0) {
SocketErrorStr(WSAGetLastError(),s1);
LogMessage(s1);
}
/* Wait for thread 4 to stop, maximum 10 seconds. */
for (WaitCount = 0; WaitCount < 100; WaitCount++) {
if (Data->Running == STOPPED) break;
Sleep(100);
}
/* Exit. */
free(Data);
_endthread();
}
/* Server thread 2: listen on the ListenSocket and start a new
thread when somebody connects. Stop when the ServiceControl()
subroutine sets the Running flag to STOPPING.*/
void Server2(struct ServerStruct *Data) {
struct ServerStruct *NewData;
char s1[BUFSIZ];
while (1) {
/* Wait for an incoming connection. */
Data->ReceiveSocket = accept(Data->ListenSocket,NULL,NULL);
/* If the service is beiing stopped then exit. */
if (ServerRunning != RUNNING) break;
/* If there was an error then write a message to the log and loop. */
if (Data->ReceiveSocket == INVALID_SOCKET) {
SocketErrorStr(WSAGetLastError(),s1);
LogMessage(s1);
continue;
}
/* Start a new thread to handle the incoming connection.
Creating the thread takes just about no time at all, so we can
immediately continue to listen for more incoming connections.
The thread will be busy for some time, but that doesn't
concern us here.
Note: the ReceiveSocket must be passed by value, not by pointer,
or the next connection will overwrite the socket. */
NewData = (struct ServerStruct *)malloc(sizeof(struct ServerStruct));
NewData->Running = RUNNING;
NewData->ForceStop = YES;
NewData->ListenSocket = Data->ListenSocket;
NewData->ReceiveSocket = Data->ReceiveSocket;
_beginthread(Server3,0,(void *)NewData);
}
/* Exit. */
ServerRunning = STOPPED;
free(Data);
_endthread();
}
/* Listen to the socket and if a remote server connects then spawn a
new thread and handle the incoming data. */
void Server(void *xxx) {
struct ServerStruct *Data;
SOCKET ListenSocket;
SOCKADDR_IN SocketControl;
int WaitCount;
char s1[BUFSIZ];
/* Create a listen-socket for the server. */
SocketControl.sin_addr.s_addr = INADDR_ANY;
SocketControl.sin_port = htons(ServerPort);
SocketControl.sin_family = AF_INET;
ListenSocket = socket(AF_INET,SOCK_STREAM,0);
if ((ListenSocket == INVALID_SOCKET) ||
(bind(ListenSocket,(LPSOCKADDR)&SocketControl,sizeof(SocketControl)) != 0) ||
(listen(ListenSocket,SOMAXCONN) != 0)) {
SocketErrorStr(WSAGetLastError(),s1);
LogMessage(s1);
if (ListenSocket != INVALID_SOCKET) closesocket(ListenSocket);
ServerRunning = STOPPED;
_endthread();
return;
}
/* Allocate a new data block in memory. */
Data = (struct ServerStruct *)malloc(sizeof(struct ServerStruct));
Data->ListenSocket = ListenSocket;
/* Start thread 2 and wait until the Running flag is STOPPING. */
if (_beginthread(Server2,0,(void *)Data)== -1) {
LogMessage("Cannot start thread 2.");
ServerRunning = STOPPED;
free(Data);
} else {
while (ServerRunning == RUNNING) Sleep(1000);
}
/* Shutdown the socket. This should cause thread 2 to unblock from
the accept() system call. */
if (closesocket(ListenSocket) != 0) {
SocketErrorStr(WSAGetLastError(),s1);
LogMessage(s1);
}
/* Wait for thread 2 to stop, maximum 10 seconds. */
for (WaitCount = 0; WaitCount < 100; WaitCount++) {
if (ServerRunning == STOPPED) break;
Sleep(100);
}
ServerRunning = STOPPED;
_endthread();
}
/**** Service ***************************************************************/
/* This function is called by the Windows Service Control Manager
when it wants the service to perform certain tasks (see
ControlService()). We don't care about most tasks, only
stopping the service is needed/implemented. */
VOID WINAPI ServiceControl(DWORD Control) {
char s1[BUFSIZ];
char s2[BUFSIZ];
if (Control = SERVICE_CONTROL_STOP) {
/* Signal the SCM that we are stopping. */
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
SetServiceStatus(ServiceHandle,&ServiceStatus);
/* Stop the listener. */
ServerRunning = STOPPING;
while (ServerRunning != STOPPED) Sleep(1000);
LogMessage("Service has stopped.");
/* Signal the SCM that we have stopped. */
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(ServiceHandle,&ServiceStatus);
return;
}
/* In all other cases give a signal to the SCM that we're still
alive and well. */
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
if (SetServiceStatus(ServiceHandle,&ServiceStatus) == 0) {
SystemErrorStr(GetLastError(),s1);
sprintf(s2,"ServiceControl(): %s",s1);
LogMessage(s2);
}
}
/* The main Service loop. This function is called by the Windows
Service Control Manager to start running the service. It will
load the configuration file from disk, initialize Winsock,
start the Listener and Watchdog threads, and then wait
forever. */
void WINAPI RunService(DWORD dwArgc, LPTSTR *lpszArgv) {
WSADATA WsaData;
int Status;
char s1[BUFSIZ];
char s2[BUFSIZ];
if (Console == NO) {
/* Register our service control handler. */
ServiceHandle = RegisterServiceCtrlHandler(SZSERVICENAME,ServiceControl);
if (ServiceHandle == 0) {
SystemErrorStr(GetLastError(),s1);
sprintf(s2,"RunService(1): %s",s1);
LogMessage(s2);
return;
}
/* Signal the Service Control Manager that we're starting. */
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = 0;
ServiceStatus.dwWin32ExitCode = NO_ERROR;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwWaitHint = 3000;
ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus(ServiceHandle,&ServiceStatus) == 0) {
SystemErrorStr(GetLastError(),s1);
sprintf(s2,"RunService(2): %s",s1);
LogMessage(s2);
return;
}
}
LogMessage("Starting service.");
/* Initialize winsock. */
Status = WSAStartup(WS_VERSION_REQD,&WsaData);
if (Status != 0) {
SocketErrorStr(WSAGetLastError(),s1);
sprintf(s2,"RunService(3): %s",s1);
LogMessage(s2);
if (Console == YES) return;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
ServiceStatus.dwServiceSpecificExitCode = Status;
SetServiceStatus(ServiceHandle,&ServiceStatus);
return;
}
/* Report SERVICE_RUNNING to the service control manager. */
if (Console == NO) {
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if (SetServiceStatus(ServiceHandle,&ServiceStatus) == 0) {
SystemErrorStr(GetLastError(),s1);
sprintf(s2,"RunService(5): %s",s1);
LogMessage(s2);
WSACleanup();
return;
}
}
/* Start new thread for the Listener. */
ServerRunning = RUNNING;
_beginthread(Server,0,(void *)0);
while(1) {
Sleep(10000);
}
/* Should never get here. */
}
/* Install the service. This function will add this program to the
list of services. The service is not yet started. */
void InstallService(void) {
SC_HANDLE ServiceHandle;
SC_HANDLE ManagerHandle;
int Result;
char s1[BUFSIZ];
ManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (ManagerHandle == NULL) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"Unable to install, %s\n",s1);
return;
}
/* Create the service. */
ServiceHandle = CreateService(
ManagerHandle, // SCManager database
SZSERVICENAME, // name of service
SZSERVICEDISPLAYNAME, // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
MyName, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
SZDEPENDENCIES, // dependencies
NULL, // LocalSystem account
NULL); // no password
/* If the service could not be created then return an error. */
if (ServiceHandle == NULL) {
Result = GetLastError();
if (Result != 1073) {
SystemErrorStr(Result,s1);
fprintf(stdout,"Unable to install, %s\n",s1);
CloseServiceHandle(ManagerHandle);
return;
}
}
/* Everything is fine. */
fprintf(stdout,"%s is now installed and can be started with\nthe Services control panel (see Windows administrative tools).\n",
SZSERVICEDISPLAYNAME,SZSERVICEDISPLAYNAME);
CloseServiceHandle(ServiceHandle);
CloseServiceHandle(ManagerHandle);
}
/* Stop and uninstall the service. The service is stopped (if
running) and removed from the list of services. */
void RemoveService(void) {
SC_HANDLE ServiceHandle;
SC_HANDLE ManagerHandle;
char s1[BUFSIZ];
/* Open a handle to the Service Control Manager. */
ManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (ManagerHandle == NULL) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"Unable to uninstall, %s\n",s1);
return;
}
/* Open a handle to the service. */
ServiceHandle = OpenService(ManagerHandle,SZSERVICENAME,SERVICE_ALL_ACCESS);
if (ServiceHandle == NULL) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"Unable to uninstall, %s\n",s1);
CloseServiceHandle(ManagerHandle);
return;
}
/* If the service is running then stop it. */
if (ControlService(ServiceHandle,SERVICE_CONTROL_STOP,&ServiceStatus) != 0) {
fprintf(stdout,"Stopping %s...\n",SZSERVICEDISPLAYNAME);
do {
Sleep(1000);
if (QueryServiceStatus(ServiceHandle,&ServiceStatus) == 0) break;
} while (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING);
if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) {
fprintf(stdout,"%s stopped.\n",SZSERVICEDISPLAYNAME);
} else {
fprintf(stdout,"%s failed to stop.\n",SZSERVICEDISPLAYNAME);
}
}
/* Now remove the service. */
if (DeleteService(ServiceHandle) != 0) {
fprintf(stdout,"%s removed.\n",SZSERVICEDISPLAYNAME);
} else {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"DeleteService failed - %s\n",s1);
}
CloseServiceHandle(ServiceHandle);
CloseServiceHandle(ManagerHandle);
}
/**** Main ******************************************************************/
int main(int argc,char **argv) {
SERVICE_TABLE_ENTRY dispatchTable[] = {
{SZSERVICENAME,(LPSERVICE_MAIN_FUNCTION)RunService},
{NULL,NULL}
};
SC_HANDLE ServiceHandle;
SC_HANDLE ManagerHandle;
SERVICE_STATUS ServiceStatus;
char s1[BUFSIZ];
char *p1;
int i;
/* Determine the paths to the executable, configuration file, and
logfile. */
GetModuleFileName(NULL,MyName,BUFSIZ);
strcpy(CfgPath,MyName);
p1 = stristr(CfgPath,".exe");
if (p1 == NULL) *CfgPath = '\0';
strcpy(p1,".cfg");
strcpy(LogPath,MyName);
p1 = stristr(LogPath,".exe");
if (p1 == NULL) *LogPath = '\0';
strcpy(p1,".log");
/* If the program was started in a DOS box (not the Windows Service
Control Manager) then write all output to stdout (instead of the
logfile) and run as a program (instead of a service) that can be
stopped with Ctrl-Break. */
if (isatty(fileno(stdin)) != 0) Console = YES;
/* Accept commandline parameters. */
if (argc > 1) {
for (i = 1; i < argc; i++) {
if (stricmp("-install",argv[i]) == 0) {
InstallService();
return(0);
}
if ((stricmp("-remove",argv[i]) == 0) ||
(stricmp("-uninstall",argv[i]) == 0)) {
RemoveService();
return(0);
}
fprintf(stdout,"%s -install Install the service\n",argv[0]);
fprintf(stdout,"%s -uninstall Uninstall the service\n",argv[0]);
return(0);
}
}
/* If the program is started in a DOS box (not the Windows Service
Control Manager) then run as a normal program (instead of a
service). The program can be stopped by CTRL-Break. */
if (Console == YES) {
/* If the server has been installed as a service and is
running, then shut it down. */
ManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (ManagerHandle != NULL) {
ServiceHandle = OpenService(ManagerHandle,SZSERVICENAME,SERVICE_ALL_ACCESS);
if (ServiceHandle != NULL) {
if (ControlService(ServiceHandle,SERVICE_CONTROL_STOP,&ServiceStatus) != 0) {
fprintf(stdout,"Stopping %s (is running as a service)...\n",SZSERVICEDISPLAYNAME);
do {
Sleep(1000);
if (QueryServiceStatus(ServiceHandle,&ServiceStatus) == 0) break;
} while (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING);
if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
fprintf(stdout,"Failed to stop. Cannot continue.\n",SZSERVICEDISPLAYNAME);
return(0);
}
fprintf(stdout,"Stopped.\n",SZSERVICEDISPLAYNAME);
}
CloseServiceHandle(ServiceHandle);
}
CloseServiceHandle(ManagerHandle);
}
/* Run as a normal program. */
RunService(0,NULL);
return(0);
}
/* Test if the service has been installed. */
ManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (ManagerHandle == NULL) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"Cannot start service, %s\n",s1);
return(0);
}
ServiceHandle = OpenService(ManagerHandle,SZSERVICENAME,SERVICE_ALL_ACCESS);
if (ServiceHandle == NULL) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"Cannot start service, %s\n",s1);
CloseServiceHandle(ManagerHandle);
return(0);
}
CloseServiceHandle(ServiceHandle);
CloseServiceHandle(ManagerHandle);
/* Run as a Windows Service. */
if (StartServiceCtrlDispatcher(dispatchTable) == 0) {
SystemErrorStr(GetLastError(),s1);
fprintf(stdout,"main(): %s\n",s1);
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -