luckfox
一般會員
發表:34 回覆:40 積分:24 註冊:2002-10-15
發送簡訊給我
|
我嚐試用winsocket寫個ftp client,目前有個問題
我下ftp的list指令,這是用sniffer看的狀況,server已經有送資料到data socket
http://tw.photo.yahoo.com/luckfox0927/ab19/p1555.jpg
可是並沒有觸發我的accept的event,這是怎麼回事,我哪裡搞錯了嗎,希望各為賢達幫我看一下... //--------------------------------------------------------------------------- #include
#pragma hdrstop #include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
USELIB("ws2_32.lib");
TForm1 *Form1;
int
ReadLine(int hSocket,char *sLine);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender)
{
if(WSAStartup(0x101,&wd)!=0)
{ StatusBar1->SimpleText="Can't Load winsock.dll";
bWSALoad=false;
}
else
{
bWSALoad=true;
Init();
} }
//---------------------------------------------------------------------------
void
__fastcall TForm1::Init()
{
LPHOSTENT lpHost;
char *pAddr;
gethostname(HostName,StrLen);
Memo3->Lines->Add("取得主機名稱 " AnsiString(HostName));
lpHost=gethostbyname(HostName);
memcpy(&MyInAddr,lpHost->h_addr_list[0],sizeof(struct in_addr));
pAddr=(char *)&MyInAddr;
Memo3->Lines->Add("取得本機IP=" AnsiString(inet_ntoa(MyInAddr)));
_getcwd(LocalDir,StrLen);
ComboBox1->Text=AnsiString(LocalDir);
last_port=FTP_DATA_BOTTOM;
bConnect=false; }
void __fastcall TForm1::Button1Click(TObject *Sender)
{
LPHOSTENT lpHost;
in_addr addr;
AnsiString asMsg; lpHost=gethostbyname(Edit1->Text.c_str());
memcpy(&ServInAddr,lpHost->h_addr_list[0],sizeof(in_addr)); Label4->Caption=AnsiString(inet_ntoa(ServInAddr));
lpHost=gethostbyaddr((char *)&ServInAddr,sizeof(ServInAddr),AF_INET); hCSocket=socket(AF_INET,SOCK_STREAM,0); ServAddr.sin_family=AF_INET;
ServAddr.sin_port=htons(FTP_PORT);
ServAddr.sin_addr=ServInAddr; if((connect(hCSocket,(sockaddr *)&ServAddr,sizeof(ServAddr)))==SOCKET_ERROR)
{
StatusBar1->SimpleText="Can't connect to " AnsiString(inet_ntoa(ServInAddr)); }
else Memo3->Lines->Add("connect to " AnsiString(inet_ntoa(ServInAddr))); //取得welcome資料
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg); //送出user資料
asMsg="USER " Edit2->Text;
SendFtpCmd(hCSocket,asMsg);
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg); //送出passwd
asMsg="PASS " Edit3->Text;
SendFtpCmd(hCSocket,asMsg);
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg); //取得Server的系統型態
SendFtpCmd(hCSocket,AnsiString("SYST"));
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg); //取得remote server 的目前目錄
asMsg=GetRemoteDir(hCSocket);
ComboBox2->Text=asMsg; //設定傳輸mode=ascii
SendFtpCmd(hCSocket,AnsiString("TYPE A"));
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg);
//建立data transfer socket
if(SendDataPort()==0) asMsg="建立Data transfer socket成功";
else asMsg="無法建立Data transfer socket";
Memo3->Lines->Add(asMsg); //取得remote server目前目錄的檔案清單
asMsg= AnsiString("LIST ") ComboBox2->Text;
SendFtpCmd(hCSocket,asMsg);
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg); }
//--------------------------------------------------------------------------- int
__fastcall TForm1::SendFtpCmd(int hSocket,AnsiString asCmd)
{
char sStr[255];
int len; asCmd=asCmd "\r\n";
len=asCmd.Length();
memcpy(sStr,asCmd.c_str(),len);
send(hSocket,sStr,asCmd.Length(),0); return 0;
}
AnsiString
__fastcall TForm1::GetFtpReply(int hSocket)
{
char buffer[255];
AnsiString asMsg; while(1)
{
if(ReadLine(hSocket,buffer)>0)
{
asMsg=asMsg AnsiString(buffer);
if(buffer[0]>='0' && buffer[0]<='9' && buffer[3]==' ')//最後一行msg
break;
} }
return asMsg;
}
int
__fastcall TForm1::ReadLine(int hSocket,char *sLine)
{
int iRet,index;
char buf[2];
bool CTL_flag=true; index=0;
while(CTL_flag)
if((iRet=recv(hSocket,buf,1,0))==1)
{//檢查是否為\n否則其餘則讀入
*(sLine index)=buf[0];
if(buf[0]=='\n') CTL_flag=false;
index ;
}
else if(iRet==0)
{//讀到檔尾了
CTL_flag=false;
}
else
{//有問題
}
*(sLine index)='\0';
return index;
} void
__fastcall TForm1::CloseConn(int hSocket)
{
// WSAAsyncSelect(hSocket,
}
AnsiString
__fastcall TForm1::GetRemoteDir(int hSocket)
{
AnsiString asMsg;
char sStr[255];
int i;
SendFtpCmd(hSocket,"PWD");
asMsg=GetFtpReply(hSocket); for(i=5;iLines->Add("socket() error!");
return -1;
}
DataAddr.sin_family=AF_INET;
DataAddr.sin_addr=MyInAddr; pAddr=(char *)&DataAddr.sin_addr;
while(1)
{
if(last_port >FTP_DATA_TOP) last_port=FTP_DATA_BOTTOM;
DataAddr.sin_port=htons(last_port); Memo3->Lines->Add("嘗試建立Data Socket IP=" AnsiString(inet_ntoa(MyInAddr))
"Port=" IntToStr(last_port));
last_port ;
if(bind(hASocket,(sockaddr *)&DataAddr,sizeof(DataAddr))==SOCKET_ERROR)
{
if((iErrorCode=WSAGetLastError())==WSAEADDRINUSE) continue;
else
{
Memo3->Lines->Add("bind() error! error code=" IntToStr(iErrorCode));
closesocket(hASocket);
return -1;
}
}
else break;
}
//設定ACCEPT和RECVICE的非同步事件處理函示
if(WSAAsyncSelect(hASocket,btnAccept->Handle,WM_KEYDOWN,FD_ACCEPT)==SOCKET_ERROR)
{
Memo3->Lines->Add("設定ACCEPT 非同步處理函式失敗");
}
if(WSAAsyncSelect(hASocket,btnRecv->Handle,WM_KEYDOWN,FD_READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR)
{
Memo3->Lines->Add("設定READ,WRITE,CLOSE 非同步處理函式失敗");
} if(listen(hASocket,1)==SOCKET_ERROR)
{
Memo3->Lines->Add("Listen() error!");
closesocket(hASocket);
return -1;
} len=sizeof(DataAddr);
//取得socket的address & port資料,確認可用
getsockname(hASocket,(sockaddr *)&DataAddr,&len);
pAddr=(char *)&(DataAddr.sin_addr);
pPort=(char *)&(DataAddr.sin_port); wsprintf(sCmdStr,"PORT %d,%d,%d,%d,%d,%d",pAddr[0],pAddr[1],pAddr[2],pAddr[3],
pPort[0],pPort[1]);
SendFtpCmd(hCSocket,AnsiString(sCmdStr));
asMsg=GetFtpReply(hCSocket);
Memo3->Lines->Add(asMsg);
return 0;
} //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(bWSALoad==true)
{
WSACleanup();
bWSALoad=false;
}
}
//--------------------------------------------------------------------------- void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
if(bWSALoad==true)
{
WSACleanup();
bWSALoad=false;
}
}
//--------------------------------------------------------------------------- void __fastcall TForm1::btnRecvMouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
while (1);
}
//--------------------------------------------------------------------------- void __fastcall TForm1::btnAcceptKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
if((hDSocket=accept(hASocket,(sockaddr *)&FromAddr,&iFromLen))<0)
{
Memo3->Lines->Add("accept() error!");
}
else Memo3->Lines->Add("accept() success!");
}
//------
|
luckfox
一般會員
發表:34 回覆:40 積分:24 註冊:2002-10-15
發送簡訊給我
|
已將此程式upload至問題程式上載區,使用bcb 6.0
|
RaynorPao
版主
發表:139 回覆:3622 積分:7025 註冊:2002-08-12
發送簡訊給我
|
引言:
已將此程式upload至問題程式上載區,使用bcb 6.0
luckfox 你好:
我已經試過你的程式碼~~希望有幾個問題能夠釐清
< class="code">
(1)這個連結 http://tw.photo.yahoo.com/luckfox0927/ab19/p1555.jpg
會產生以下的錯誤
You don't have permission to access /luckfox0927/ab19/p1555.jpg on this server.
(> --
------ -- 若您已經得到滿意的答覆,請適時結案!! --
-- 欲知前世因,今生受者是;欲知來世果,今生做者是 --
-- 一切有為法,如夢幻泡影,如露亦如電,應作如是觀 --
|
luckfox
一般會員
發表:34 回覆:40 積分:24 註冊:2002-10-15
發送簡訊給我
|
0.謝謝你的答覆
1.已經將圖檔放置圖檔存放區了
2.這三個warning我想並不會影響程式的運作
304行,因為都無法accept,如何receive ,所以此行不影響
316行,或可改成if((hDSocket=accept(hASocket,(sockaddr *) &FromAddr,&iFromLen))!=SOCKET_ERROR)
3.我的問題是,當我connect到ftp Server(port 21)後,下list命令(取得ftp server的file list),server已經有傳資料,但是我的data socket並沒有收到accept ,意即當server從data port(port 20)傳資料過來後,我的line 316行if((hDSocket=accept(hASocket,(sockaddr *)&FromAddr,&iFromLen))<0)應該會被執行到 ,因為我在line 249 if(WSAAsyncSelect(hASocket,btnAccept->Handle,WM_KEYDOWN,FD_ACCEPT)==SOCKET_ERROR) 並沒有問題
,然而事實上,在line 316行下 break point,並不會break到
|
skcc
中階會員
發表:36 回覆:96 積分:88 註冊:2002-08-28
發送簡訊給我
|
引言:
0.謝謝你的答覆
1.已經將圖檔放置圖檔存放區了
2.這三個warning我想並不會影響程式的運作
304行,因為都無法accept,如何receive ,所以此行不影響
316行,或可改成if((hDSocket=accept(hASocket,(sockaddr *) &FromAddr,&iFromLen))!=SOCKET_ERROR)
3.我的問題是,當我connect到ftp Server(port 21)後,下list命令(取得ftp server的file list),server已經有傳資料,但是我的data socket並沒有收到accept ,意即當server從data port(port 20)傳資料過來後,我的line 316行if((hDSocket=accept(hASocket,(sockaddr *)&FromAddr,&iFromLen))<0)應該會被執行到 ,因為我在line 249 if(WSAAsyncSelect(hASocket,btnAccept->Handle,WM_KEYDOWN,FD_ACCEPT)==SOCKET_ERROR) 並沒有問題
,然而事實上,在line 316行下 break point,並不會break到
請先確認你的 FTP Server 是 Passive 還是 Active 模式? Anthony Lee
|
luckfox
一般會員
發表:34 回覆:40 積分:24 註冊:2002-10-15
發送簡訊給我
|
我不太清楚你的意思,對ftp client而言,他可以提出passive或非passive的要求(我是採用非passive),似乎和server無關
passive->由ftp server提出Server Data port
非passive ->由ftp client提出client的Data port
(見圖檔上傳區) 目前已經知道我有成功的送出port命令,並且可以下list命令,server也送到正確的client data port(見圖檔上傳區),(我程式給的client data port是40000)然而我的accept就是無法觸發.....
|