如何在子线程中向主线程发送消息,让主线程结束,程序中止。
下面一段代码是借用站上一位朋友sadf的,程序实现的是一个telnet服务器程序,输入exit,客户端与服务器断开。我想加上一个,输入shutdown,telnet服务器程序退出。由于与客户端打交道的是telnet服务器产生的一个子线程,则应该由子线程接收quit命令,然后由该子线程向主线程发送消息,令主线程结束。
//连接端口是4250,连接后没有回显,直接输密码123456就可以进去了。
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
/*
MyRecv的功能是在一个指定的套接字*psockid上接受最多buflen个字符
到pbuf指向的缓冲区中,或是收到回车也返回,因为telnet是按一下键发一个字符的
*/
long MyRecv(SOCKET *psockid=NULL,
char *pbuf=NULL,
const unsigned long buflen=0);
DWORD WINAPI UserThread(SOCKET *UserSockid=NULL);
const char *baner = "\n\rAuthor:\tsjdf\n\rEmail:\tsjdf1@163.com\n\r\n\r";
const char *pwd = "123456";
int pwdlen = strlen(pwd);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
const unsigned short myport = 4250;
WSADATA wsadata;
if (WSAStartup(MAKEWORD(2,0),&wsadata) != 0)
{
return 1;
}
SOCKET sockid = INVALID_SOCKET;
if ((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
sockaddr_in srv_addr;
int addrlen = sizeof(srv_addr);
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.S_un.S_addr = INADDR_ANY;
srv_addr.sin_port = htons(myport);
memset(&srv_addr.sin_zero,0,8);
if (bind(sockid,(sockaddr*)&srv_addr,addrlen) < 0)
{
closesocket(sockid);
WSACleanup();
return 1;
}
listen(sockid,3);
SOCKET *msgsockid = NULL;
DWORD threadid;
while (true) //循环等待,如有新的连接请求就接收
{
msgsockid = new SOCKET;
*msgsockid = accept(sockid, (sockaddr*)&srv_addr,NULL);
if (*msgsockid == INVALID_SOCKET)
{
delete msgsockid;
Sleep(1000);
}
else
{
if (CreateThread(0,
0,
(LPTHREAD_START_ROUTINE)UserThread,
msgsockid,
0,
&threadid) == NULL)
{
delete msgsockid;
Sleep(1000);
}
}
}
return 0;
}
long MyRecv(SOCKET *psockid,char *pbuf,const long buflen)
{
memset(pbuf,0,buflen);
long count = 0;
do
{
if (count >= buflen)
{
return count;
}
if (recv(*psockid,pbuf+count,1,0) < 0)
{
return -1;
}
}while (pbuf[count++] != '\n');
return count;
}
//为每个用户使用这个线程创建shell
DWORD WINAPI UserThread(SOCKET *UserSockid)
{
char recvbuf[1024];
char sendbuf[2048];
const long recvbuflen = sizeof(recvbuf);
const long sendbuflen = sizeof(sendbuf);
unsigned long cmdtouserlen,usertocmdlen;
HANDLE hClientReadPipe, hClientWritePipe;
HANDLE hCmdWritePipe, hCmdReadPipe;
PROCESS_INFORMATION processinfo;
//接收口令
if (MyRecv(UserSockid,recvbuf,recvbuflen) < 0)
{
goto exit3;
}
//验证口令
if (memcmp(recvbuf,pwd,pwdlen) != 0)
{
goto exit3;
}
//发送登录Baner
if (send(*UserSockid,baner,strlen(baner),0) < 0)
{
goto exit3;
}
//创建管道
SECURITY_ATTRIBUTES pipeattr;
pipeattr.nLength = sizeof(SECURITY_ATTRIBUTES);
pipeattr.lpSecurityDescriptor = NULL;
pipeattr.bInheritHandle = TRUE;
if (CreatePipe(&hClientReadPipe,
&hCmdWritePipe,
&pipeattr,
0) == 0)
{
goto exit3;
}
if (CreatePipe(&hCmdReadPipe,
&hClientWritePipe,
&pipeattr,
0) == 0)
{
goto exit4;
}
//启动cmd.exe
STARTUPINFO startinfo;
GetStartupInfo(&startinfo);
startinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
startinfo.hStdInput = hCmdReadPipe;
startinfo.hStdError = hCmdWritePipe;
startinfo.hStdOutput = hCmdWritePipe;
startinfo.wShowWindow = SW_HIDE;
char szAPP[256];
GetSystemDirectory(szAPP,MAX_PATH+1);
strcat(szAPP,"\\cmd.exe");
if (CreateProcess(szAPP,
NULL,
NULL,
NULL,
true,
0,
NULL,
NULL,
&startinfo,
&processinfo) == 0)
{
goto exit5;
}
while(true)
{
if (PeekNamedPipe(hClientReadPipe,
sendbuf,
sendbuflen,
&cmdtouserlen,
0,
0) == 0)
{
goto exit5;
}
if(cmdtouserlen == 0)
{
if ((usertocmdlen=MyRecv(UserSockid,recvbuf,recvbuflen)) < 0)
{
goto exit5;
}
if (memcmp(recvbuf,"exit",4) == 0)
{
goto exit5;
}
if (WriteFile(hClientWritePipe,
recvbuf,
usertocmdlen,
&usertocmdlen,
0) == 0)
{
goto exit5;
}
Sleep(200);
}
else
{
memset(sendbuf,0,sendbuflen);
if (ReadFile(hClientReadPipe,
sendbuf,
cmdtouserlen,
&cmdtouserlen,0) == 0)
{
goto exit5;
}
if (send(*UserSockid,sendbuf,cmdtouserlen,0) == SOCKET_ERROR)
{
goto exit5;
}
}
}
exit5: CloseHandle(hCmdReadPipe);
exit4: CloseHandle(hClientReadPipe);
exit3: closesocket(*UserSockid);
exit2: delete UserSockid;
exit1: return 1;
}