(一)項目概述:
C++服務器是之前編寫好的,有對應的C++客戶端。因此,服務器的C++代碼不能改變。主要解決的問題是:
1.如何用java類來還原服務器中的結構體
2.數據之間的轉換
3.socket通信數據統一用字節數組。
(二)首先看一下服務器的代碼:(360安全衛士竟然說我的代碼是木馬...好吧,這個服務器不就是能聯網,能獲取本地數據麼?確實有點像木馬,但絕對不是!)
/*主要功能是獲得系統硬盤符號及硬盤下的目錄和文件*/
[C++ code]
[cpp]
// FileNetServer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "FileNetServer.h"
#include <winsock.h>
#include <windows.h>
#include "SYS.H"
#pragma comment(lib, "ws2_32")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
typedef struct
{
int ID;
BYTE lparam[BUF_LEN*2];
}COMMAND;
/*BOOL 4byte HICON 4byte*/
typedef struct
{
char FileName[MAX_PATH];//260byte
int FileLen;
char Time[50];
BOOL IsDir;
BOOL Error;
HICON hIcon;
}FILEINFO;
BOOL DeleteDirectory(char *DirName);
BOOL CapScreen(LPTSTR FileName);
DWORD WINAPI SLisen(LPVOID lparam);
DWORD GetDriverProc(COMMAND command, SOCKET client);
DWORD GetDirInfoProc(COMMAND command, SOCKET client);
DWORD ExecFileProc(COMMAND command, SOCKET client);
DWORD DelFileProc(COMMAND command, SOCKET client);
DWORD FileInfoProc(COMMAND command, SOCKET client);
DWORD CreateDirProc(COMMAND command, SOCKET client);
DWORD DelDirProc(COMMAND command, SOCKET client);
DWORD GetFileProc(COMMAND command, SOCKET client);
DWORD PutFileProc(COMMAND command, SOCKET client);
DWORD GetScreenProc(COMMAND command, SOCKET client);
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
WSADATA wsadata;
SOCKET FileNetServer;
SOCKET client;
SOCKADDR_IN FileNetServeraddr;
SOCKADDR_IN clientaddr;
int port = 17329;
WORD ver = MAKEWORD(2,2);
WSAStartup(ver, &wsadata);
FileNetServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
FileNetServeraddr.sin_family = AF_INET;
FileNetServeraddr.sin_port = htons(port);
FileNetServeraddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
bind(FileNetServer, (SOCKADDR*)&FileNetServeraddr, sizeof(FileNetServeraddr));
listen(FileNetServer, 5);
int len = sizeof(clientaddr);
char s_password[100];
while(true)
{
if(client = accept(FileNetServer, (sockaddr*)&clientaddr, &len))
{
if(send(client, "Password", sizeof("Password"), 0) != SOCKET_ERROR)
{
cout<<"有客戶請求連接,正在等待客戶輸入密碼!";
}
ag: if(recv(client, s_password, sizeof(s_password), 0) != SOCKET_ERROR)
{
if(strcmp(s_password, "123") == 0)
{
send(client, "OK", sizeof("OK"), 0);
cout<<"CreateThread is the OK \n";
CreateThread(NULL, NULL, SLisen, (LPVOID)client, NULL, NULL);
}
else
{
cout<<"有用戶試圖聯入,但是未能輸入正確密碼!/n";
send(client, "NOOK", sizeof("NOOK"), 0);
goto ag;
}
}
}
}
closesocket(FileNetServer);
closesocket(client);
WSACleanup();
return 0;
}
DWORD WINAPI SLisen(LPVOID lparam)
{
SOCKET client = (SOCKET)lparam;
COMMAND command;
while(1)
{
memset((char*)&command, 0, sizeof(command));
if(recv(client, (char*)&command, sizeof(command), 0) == SOCKET_ERROR)
{
cout<<"The Client Socket is Closed\n";
break;
}
else
{
cout<<"The recv command is: ID="<<command.ID<<" lparam="<<command.lparam<<endl;
switch(command.ID)
{
case GetDriver:
GetDriverProc(command, client);
break;
case GetDirInfo:
GetDirInfoProc(command, client);
break;
case ExecFile:
ExecFileProc(command, client);
break;
case DelFile:
DelFileProc(command, client);
break;
case FileInfo:
FileInfoProc(command, client);
break;
case CreateDir:
CreateDirProc(command, client);
break;
case DelDir:
DelDirProc(command, client);
break;
case GetFile:
GetFileProc(command, client);
break;
case PutFile:
PutFileProc(command, client);
break;
case GetScreen:
GetScreenProc(command, client);
break;
default:
cout<<"Can not recongnize the command!\n";
break;
}
}
}
closesocket(client);
return 0;
}
DWORD GetDriverProc(COMMAND command, SOCKET client)
{
cout<<"GetDriver is ok\n";
COMMAND cmd;
memset((char *)&cmd, 0, sizeof(cmd));
cmd.ID = GetDriver;
for(char i='A'; i<'Z'; i++)
{
char x[20] = {i, ':'};
UINT Type = GetDriveType(x);
if(Type==DRIVE_FIXED || Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM)
{
cout<<x<<"\n";
memset((char*)cmd.lparam, 0, sizeof(cmd.lparam));
strcpy((char*)cmd.lparam, x);
if(send(client, (char*)&cmd, sizeof(cmd), 0) == SOCKET_ERROR)
{
cout<<"Send Driver is Error\n";
}
}
}
return 0;
}
DWORD GetDirInfoProc(COMMAND command, SOCKET client)
{
cout<<"GetDir is Ok\n";
FILEINFO fi;
COMMAND cmd;
memset((char*)&cmd, 0, sizeof(cmd));
memset((char*)&fi, 0, sizeof(fi));
strcat((char*)command.lparam, "*.*");
cout<<(char*)command.lparam<<"\n";
CFileFind file;
BOOL bContinue = file.FindFile((char*)command.lparam);
while(bContinue)
{
memset((char*)&cmd, 0, sizeof(cmd));
memset((char*)&fi, 0, sizeof(fi));
bContinue = file.FindNextFile();
if(file.IsDirectory())
{
fi.IsDir = true;
}
strcpy(fi.FileName, file.GetFileName().LockBuffer());
cout<<fi.FileName<<"\n";
cmd.ID = GetDirInfo;
memcpy((char*)&cmd.lparam, (char*)&fi, sizeof(fi));
if(send(client, (char*)&cmd, sizeof(cmd), 0) == SOCKET_ERROR)
{
cout<<"Send Dir is Error\n";
}
}
return 0;
}
DWORD ExecFileProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD DelFileProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD FileInfoProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD CreateDirProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD DelDirProc(COMMAND command, SOCKET client)
{
return 0;
}
BOOL DeleteDirectory(char *DirName)
{
return 0;
}
DWORD GetFileProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD PutFileProc(COMMAND command, SOCKET client)
{
return 0;
}
DWORD GetScreenProc(COMMAND command, SOCKET client)
{
return 0;
}
BOOL CapScreen(LPTSTR FileName)
{
return 0;
}
(三)最主要的是客戶端如何編寫:
當然,編程流程和博客[http://blog.csdn.net/nuptboyzhb/article/details/8041715]是一樣的。主要有一下幾個類:
1.Client.java //還有main函數的類,你們都知道它是功能。
[java]
/*
*@author: ZhengHaibo
*web: blog.csdn.net/nuptboyzhb
*mail: [email protected]
*2012-9-23 Nanjing njupt
*/
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
NetDataTypeTransform mNetDataTypeTransform=new NetDataTypeTransform();
private static final String IP="127.0.0.1";
private static final int NetPort=17329;
private Socket sock;
public Client(){
try {
onCreate();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void onCreate() throws IOException{
InetSocketAddress addr = new InetSocketAddress(IP,NetPort); //創建socket
sock = new Socket();
sock.connect(addr);//連接服務器
byte []receive=new byte[9];
sock.getInputStream().read(receive);
String tempString=mNetDataTypeTransform.ByteArraytoString(receive, receive.length);
System.out.println(" Server said:send your "+tempString);
if(tempString.equals("Password")){
System.out.println("I can send password 123\0!");
}
String password="123\0";//注意,別忘了‘\0’
sock.getOutputStream().write(mNetDataTypeTransform.StringToByteArray(password));
byte []isOk=new byte[3];
sock.getInputStream().read(isOk);
String okString=mNetDataTypeTransform.ByteArraytoString(isOk,isOk.length);
System.out.println(" ----- is ok?--"+okString);
if(okString.equals("OK")){
System.out.println("new Thread begin...");
NetDataCommand commd=new NetDataCommand(1,"E:\0");
sock.getOutputStream().write(commd.getByteArrayData());
ThreadRead mThreadRead=new ThreadRead(sock,this);
mThreadRead.start();//啟動監聽線程。
}
//////////////////////////////////////////////////////////////
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String [] args) throws InterruptedException, IOException
{
new Client();
}
public void GetDriverPro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"--"+"command Lparam="+mCommand.getLparam());
NetDataCommand commd=new NetDataCommand(2,mCommand.getLparam()+"\\\0");
try {
mSocket.getOutputStream().write(commd.getByteArrayData());
} catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void GetDirInfoPro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void ExecFilePro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void DelFilePro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void FileInfoPro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void CreateDirPro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void GetFilePro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void PutFilePro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
public void GetScreenPro(Socket mSocket,NetDataCommand mCommand){
System.out.println("command ID="+mCommand.getID()+"command Lparam="+mCommand.getLparam());
}
}
2.NetDataTypeTransform.java//顧名思義:數據轉換的類
[java]
import java.io.UnsupportedEncodingException;
/*
*@author: ZhengHaibo
*web: blog.csdn.net/nuptboyzhb
*mail: [email protected]
*2012-9-25 Nanjing njupt
*/
public class NetDataTypeTransform {
public NetDataTypeTransform(){
}
/**
* 將int轉為低字節在前,高字節在後的byte數組
*/
public byte[] IntToByteArray(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* byte數組轉化為int
* 將低字節在前轉為int,高字節在後的byte數組
*/
public int ByteArrayToInt(byte[] bArr) {
int n = 0;
for(int i=0;i<bArr.length&&i<4;i++){
int left = i*8;
n+= (bArr[i] << left);
}
return n;
}
/**
* 將byte數組轉化成String
*/
public String ByteArraytoString(byte[] valArr,int maxLen) {
String result=null;
int index = 0;
while(index < valArr.length && index < maxLen) {
if(valArr[index] == 0) {
break;
}
index++;
}
byte[] temp = new byte[index];
System.arraycopy(valArr, 0, temp, 0, index);
try {
result= new String(temp,"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public byte[] StringToByteArray(String str){
byte[] temp = null;
try {
temp = str.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return temp;
}
}
3.NetDataCommand.java//該類就是實現與C++服務器中COMMMAND結構體對應的java類
[java]
/*
*@author: ZhengHaibo
*web: blog.csdn.net/nuptboyzhb
*mail: [email protected]
*2012-9-26 Nanjing njupt
*/
public class NetDataCommand {
private static final int IDLen=4;
private static final int LparamLen=2048;
private static final int CommandLen=2052;
public byte []byteArrayData=new byte[CommandLen];
private int ID;
private String lparam;
private NetDataTypeTransform mDataTypeTransform=new NetDataTypeTransform();;
public byte[] getByteArrayData(){
return byteArrayData;
}
public NetDataCommand(){
}
public NetDataCommand(int ID,String lparam) {
// TODO Auto-generated constructor stub
this.ID=ID;
this.lparam=lparam;
byte[] IDbyte = mDataTypeTransform.IntToByteArray(ID);
System.arraycopy(IDbyte,0, byteArrayData, 0, IDbyte.length);
byte[] Strbyte = mDataTypeTransform.StringToByteArray(lparam);
System.arraycopy(Strbyte,0,byteArrayData,IDbyte.length,Strbyte.length);
}
public NetDataCommand(byte[] dataArray){
int id=1;
String lpString="";
System.arraycopy(dataArray,0, byteArrayData,0,CommandLen);
byte[] forIntID = new byte[IDLen];
System.arraycopy(dataArray,0,forIntID,0,forIntID.length);
id=mDataTypeTransform.ByteArrayToInt(forIntID);
byte[] StrTemp=new byte[LparamLen];
System.arraycopy(dataArray,IDLen,StrTemp,0,StrTemp.length);
lpString=mDataTypeTransform.ByteArraytoString(StrTemp, StrTemp.length);
//lpString=StrTemp.toString();
ID=id;
lparam=lpString;
}
public int getID(){
return ID;
}
public String getLparam(){
return lparam;
}
public void setID(int id) {
this.ID=id;
}
public void setLparam(String str){
this.lparam=str;
}
}
4.ThreadRead.java//線程,用於一直接收數據。
[java]
/*
*@author: ZhengHaibo
*web: blog.csdn.net/nuptboyzhb
*mail: [email protected]
*2012-9-26 Nanjing njupt
*/
import java.io.IOException;
import java.lang.Thread;
import java.net.Socket;
public class ThreadRead extends Thread{
public Socket mSocket;
public Client mClient;
private static final int GetDriver=0x01;
private static final int GetDirInfo=0x02;
private static final int ExecFile=0x03;
private static final int GetFile=0x04;
private static final int PutFile=0x05;
private static final int DelFile=0x06;
private static final int DelDir =0x07;
private static final int CreateDir=0x08;
private static final int FileInfo=0x09;
private static final int GetScreen=0x10;
private static final int CommandLen=2052;
private static int TryTimes=5;
private byte []byteArrayData=new byte[CommandLen];
public ThreadRead(Socket lpSocket,Client mClient) {
// TODO Auto-generated constructor stub
this.mSocket=lpSocket;
this.mClient=mClient;
}
public void run() {
while (TryTimes>0) {
while (true) {
try {
mSocket.getInputStream().read(byteArrayData);
NetDataCommand mCommand = new NetDataCommand(byteArrayData);
switch (mCommand.getID()){
case GetDriver:
mClient.GetDriverPro(mSocket, mCommand);
break;
case GetDirInfo:
mClient.GetDirInfoPro(mSocket, mCommand);
break;
case ExecFile:
mClient.ExecFilePro(mSocket, mCommand);
break;
case DelFile:
mClient.DelFilePro(mSocket, mCommand);
break;
case FileInfo:
mClient.FileInfoPro(mSocket, mCommand);
break;
case CreateDir:
mClient.CreateDirPro(mSocket, mCommand);
break;
case DelDir:
mClient.DelFilePro(mSocket, mCommand);
break;
case GetFile:
mClient.GetFilePro(mSocket, mCommand);
break;
case PutFile:
mClient.PutFilePro(mSocket, mCommand);
break;
case GetScreen:
mClient.GetScreenPro(mSocket, mCommand);
break;
default:
System.out.println("----------wrong!!!--------------");
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
TryTimes--;
break;
}
}
}
}
}
(四)實現結果
項目源碼:http://download.csdn.net/detail/nuptboyzhb/4624574
先運行服務器,再運行java客戶端代碼。實驗結果如下:(當然,這是我電腦下的文件夾和文件(隱私暴漏了...))
運行服務器的時候,我真的想告訴360安全衛士,這不是木馬...
Eclipse的控制台:
[plain]
Server said:send your Password
I can send password 123
----- is ok?--OK
new Thread begin...
command ID=1--command Lparam=C:
command ID=1--command Lparam=D:
command ID=1--command Lparam=E:
command ID=1--command Lparam=F:
command ID=1--command Lparam=G:
command ID=2command Lparam=$Recycle.Bin
command ID=2command Lparam=.rnd
command ID=2command Lparam=360Rec
command ID=2command Lparam=360SANDBOX
command ID=2command Lparam=9c3e42423a202668d396d3be5e
command ID=2command Lparam=autoexec.bat
command ID=2command Lparam=bar.emf
command ID=2command Lparam=config.sys
command ID=2command Lparam=cygwin
command ID=2command Lparam=Documents and Settings
command ID=2command Lparam=hiberfil.sys
command ID=2command Lparam=IO.SYS
command ID=2command Lparam=MSDOS.SYS
command ID=2command Lparam=MSOCache
command ID=2command Lparam=pagefile.sys
command ID=2command Lparam=PerfLogs
command ID=2command Lparam=Program Files
command ID=2command Lparam=ProgramData
command ID=2command Lparam=Recovery
command ID=2command Lparam=System Volume Information
command ID=2command Lparam=Users
command ID=2command Lparam=Windows
command ID=2command Lparam=$RECYCLE.BIN
command ID=2command Lparam=eclipse
command ID=2command Lparam=HelloJNI
command ID=2command Lparam=System Volume Information
command ID=2command Lparam=大學部分資料
command ID=2command Lparam=文件魚龍混雜
command ID=2command Lparam=照片和視頻
command ID=2command Lparam=研究方向
command ID=2command Lparam=研究生學習
command ID=2command Lparam=程序語言
command ID=2command Lparam=軟件安裝包
command ID=2command Lparam=$RECYCLE.BIN
command ID=2command Lparam=360
command ID=2command Lparam=360Downloads
command ID=2command Lparam=360Rec
command ID=2command Lparam=360雲盤
command ID=2command Lparam=360驅動大師目錄
command ID=2command Lparam=61ffd6de5ad141016097
command ID=2command Lparam=android-sdk-windows
command ID=2command Lparam=CSDN_ExportBlog
command ID=2command Lparam=eclipse
command ID=2command Lparam=EditPlus
command ID=2command Lparam=Fetion2012
command ID=2command Lparam=FlashFXP_4.2.4.1785
command ID=2command Lparam=JDK1_6
command ID=2command Lparam=kankan
command ID=2command Lparam=KMPlayer
command ID=2command Lparam=KSafeRecycle
command ID=2command Lparam=Kugou
command ID=2command Lparam=KuGouCache
command ID=2command Lparam=matlab2009a
command ID=2command Lparam=msdn6_0
command ID=2command Lparam=MSOCache
command ID=2command Lparam=MySQL Tools
command ID=2command Lparam=PDF_Reader
command ID=2command Lparam=PHPEclipse
command ID=2command Lparam=Program Files
command ID=2command Lparam=ps3
command ID=2command Lparam=Python27
command ID=2command Lparam=QQ
command ID=2command Lparam=QQGame
command ID=2command Lparam=sogou
command ID=2command Lparam=System Volume Information
command ID=2command Lparam=TDDOWNLOAD
command ID=2command Lparam=Ubuntu
command ID=2command Lparam=vc2008
command ID=2command Lparam=vc6_0
command ID=2command Lparam=VC98
command ID=2command Lparam=Video
command ID=2command Lparam=VMware
command ID=2command Lparam=WAMP5
command ID=2command Lparam=WindowsManagerTools
command ID=2command Lparam=youku
command ID=2command Lparam=光影看看
command ID=2command Lparam=快捷方式
command ID=2command Lparam=有道
command ID=2command Lparam=迅雷7
服務器的顯示: