»ùÓÚselect I/OÄ£Ð͵ÄÔ¶³ÌĿ¼ä¯ÀÀÓë¶àÏß³ÌÎļþÏÂÔØ
×÷ÕߣºÀ³É
ͻ񻣼
·þÎñÆ÷¶Ë»ùÓÚselect I/OÄ£ÐÍ¡£Îª·ÀÖ¹³ÌÐò½çÃæ×èÈû, ÓÐÒ»¸ö×ÓÏß³ÌÓÃÓÚ²»¶Ï½ÓÊÕsocket²¢selectÆäÖеĴ¦Àí¡£¿Í»§¶ËÖ»ÓÐÒ»¸öÏ̺߳¯Êý, ²»¹ýÆäÀûÓÃÂʺܸß, ¿ÉÓÃÓÚÔ¶³ÌĿ¼½»»», ÇëÇóÎļþ´óС, ´´½¨Èô¸ÉÏß³ÌÀ´ÏÂÔØÎļþ¡£Îļþ´«ÊäÓÐÉÏ´«ºÍÏÂÔØ,»¹ÓжԵȴ«Êä, Õâ¸öÏîÄ¿ÖÐ, ´«ÊäÎļþ¾ßÌåÖ¸ÏÂÔØ¡£
ÕýÎÄ£º
Ò»¡¡Êý¾Ý¼°Êý¾Ý½á¹¹
1 ´«ËͰü, ¿Í»§¶ËÖ÷Ï̸߳ø×ÓÏ̴߳«µÝµÄ½á¹¹Ìå
typedef struct{
char packetType; // ÇëÇóÀàÐÍ r£ºrequest rootdriver¡¡d£ºdirectory f£ºfile D£º:data
unsigned int length; //ÓÃÓÚ´«ËÍintÀàÐÍ
char content[2000]; //´«Ë͵ÄÄÚÈÝ
}DATA_PACKET;
ÇëÇóÀàÐÍ£º'r'£º·þÎñÆ÷Âß¼ÅÌ·û, d; ÅÌ·ûºÍÎļþ¼ÐϵÄÎļþ¼ÐºÍÎļþÃû, f'£ºÎļþ´óС, D£ºÎļþÄÚÈÝ¡£
ÔÚ¿Í»§¶ËÇëÇóÏÂÔØÎļþ, lengthÄ©Á½Î»ÓÃÓڼǼÏÂÔØµÄÏß³Ì×ÜÊý, Ç°ÃæµÄÓÃÓڼǼµ±Ç°µÄÏß³ÌÐòºÅ¡£ÔÚ·þÎñÆ÷¶ËÕâ¸ö·´ÔËËãºÜÈÝÒ×ʵÏÖ¡£
ÔÚÇëÇóÎļþ´óСºÍÇëÇóÏÂÔØÊ±, content¶¼ÓÃÓÚ±£´æÇëÇóÎļþµÄ¾ø¶Ô·¾¶.Õâ¸öÔÚ·þÎñÆ÷¶Ë×ö·´ÔËËãÒªÓÃ×Ô¶¨Ò庯Êý´¦Àí¡£
2¡¡ È«¾Ö±äÁ¿(ÓÃÓÚÏ̼߳äµÄͨÐÅ)
char* pDrives; // Êý¾Ý»º³å
CString arrFiles[200];//ÎļþĿ¼×Ö·û´®Êý×é
CString savePath; //Îļþ±£´æÂ·¾¶
long fSize=0l, ,recvFSize=0l;//Îļþ´óС,ÒѾ½ÓÊÕµÄÎļþ´óС
CString strIP;//IP
bool thrFlag=false;¡¡¡¡//ÏÂÔØÏ̴߳´½¨ÖÃλ
ÀíÂÛÉϽ², ÔÚ³ÌÐòÖÐÓ¦¾¡Á¿±ÜÃâʹÓÃÈ«¾Ö±äÁ¿,ÒòÎªÆÆ»µ³ÌÐò½á¹¹, ¾ý²»¼ûJavaºÍC#ÍêÈ«ÃæÏòÀà¡£µ«ÎªÁË·½±ã, ËùÒÔ¾ÍÓÃÁËÈ«¾Ö±äÁ¿, ÇÒÊÇÓ¦ÓóÌÐò¼¶µÄ, ÕâÑùÏ̼߳äµÄͨѶºÜ·½±ã¡£ÖµµÃÒ»ÌáµÄÊÇ, ÕâÀïthrFlagºÜÖØÒª, ËüÉæ¼°µ½È·±£Ï̴߳´½¨Ò»¶¨ÕýÈ·µÄÎÊÌâ, ÔÚºóÃæ¡°Òª×¢ÒâµÄ¼¸µãÎÊÌ⡱Öлá¸üÏêϸµÄÌÖÂÛ¡£
3 Ŀ¼Ê÷ÀàCExtnTreeCtrl::CTreeCtrl
¸ÃÀà¼Ì³ÐÓÚCTreeCtrlÀà, Ö÷ÒªÀ©Õ¹»ñµÃÊ÷µÄij¸öÏîÄ¿ÔÚÕû¿ÃÊ÷µÄÍêÕû·¾¶, ÒÔ±ã°ÑÕâ¸ö·¾¶¹æ¸ñ»¯ºóÄÜÏò·þÎñÆ÷ÇëÇóÎļþ¡£ÔÚÕâÀﻹʵÏÖÁ˽«Ò»¸öÍêÕû·¾¶×ªÎªÎļþÃûµÄº¯Êý¡£
¶ÔÓÚÈçºÎ¹¹ÔìÕâ¿ÃÊ÷, ÓÐÒ»¸öºÜ·½±ã¸ßЧµÄ°ì·¨£ºË«»÷Ê÷,°ÑË«»÷µÄÏî×÷Ϊ¸ù.Èç¹ûΪÅÌ·û»òÎļþ¼Ð, ¾Í·¢ËÍÇëÇó¸ø·þÎñÆ÷, ´ý·þÎñÆ÷·µ»Ø, ×Ô¶¯Ìî³äÔÚÕâ¸öÏîÏ¡£Èç¹ûΪÎļþ, Ôò¸ÃÏîÃûÓÐÀ©Õ¹Ãû, ½«ÇëÇóÏÂÔØ¡£Õâ¸ö°ì·¨²Ù×÷ÆðÀ´·½±ã, ¶øÇÒ»¹Ìá¸ßÁËϵͳÐÔÄÜ, ÖÁÉÙÔÚ¾ÖÓòÍøÊÇÕâÑù¡£Èç¹û¾ÍÒ»´Î´Ó·þÎñÆ÷ÖÐÇëÇóÕû¸öÎļþϵͳµÄĿ¼ÄÚÈÝ, ¿Ï¶¨»áÂýºÜ¶à¡£
4.²ÎÊýÉèÖöԻ°¿òÀà CSetParam
Õâ¸öÀàÓÃÓÚÉèÖÃÏÂÔØµÄÏß³ÌÊýÄ¿, ºÍĬÈϵı£´æÎļþ¼Ð·¾¶¡£Õâ¸öÀà»áдһ¸ö¡°Setting.ini¡±ÎļþÔÚCÅÌÒÔ±£´æ²ÎÊý¡£¾ßÌåÀ´Ëµ,Èç¹ûÓû§Ò»Ö±¶¼Ã»ÓÐÉèÖÃÕâЩ²ÎÊýµÄ»°, ÄÇôGetPrivateProfileString(...)ÊÔͼ¶ÁÈ¡"C:\Setting.ini"Îļþ»á·µ»ØÄ¬ÈϵÄÏß³ÌÊý0, ºÍÒ»¸ö²»ÊDZíʾ·¾¶µÄ×ÖÌõ´®¡°defaultpath¡±, Õâʱ, ÏÂÔØ³ÌÐò»á×Ô¶¯ÉèÖòÎÊý, ·Ö±ðΪ3, ¡°C:\¡±¡£
¶þ¡¡¼¸¸öҪעÒâµÄÎÊÌâ
1¡¡MFCÓëWindows API
¾Í¶àÏ̱߳àÐ´ÍøÂç³ÌÐò¶øÑÔ, Èç¹ûʹÓÃMFCµÄCAsyncSocket»òCSocket, Ö÷Ï̸߳ø×ÓÏ̴߳«²ÎÁ¿ÊÇÒ»¸ö·Ç³£Í·Í´µÄÎÊÌâ, Èç¹ûÓÃWindows
APIʵÏÖ¾ÍÁé»î¶àÁË¡£ÔÚÎļþ²Ù×÷·½Ãæ, CFile»¹²»´í¡£¾¡¹ÜÈç´Ë, ÎÒ»¹ÊÇÓÃÁËWindows APIº¯Êý, ΪÁËÉè¼ÆÂú×ãÒªÇó¡£
2¡¡ socket´«ËÍ×Ö·û´®»ò×Ö·û´®Êý×é
ÀíÂÛÉÏ, sendÊǵײ㺯Êý, Ö»ÒªÖ¸¶¨»º³åÇøÊ×µØÖ·Ö¸ÕëºÍ»º³åÇø´óС, ²»¹Üʲô¹·ÊºÀ¬»øËü¶¼»á°ïÄã°ÑÕâÆ¬ÄÚ´æµÄÄÚÈÝsend ³öÈ¥¡£È»¶ø, Èç¹ûÊÇ×Ö·û´®Êý×éÉõÖÁ×Ö·û´®, »òÕß°üº¬ÕâÁ½Õ߯äÖÐÖ®Ò»µÄ·â°ü, ÄÚÈÝÊDZ»
send ×ßÁË, ½ÓÊÕ¶Ë»º³åÇøÒ²ÏÔʾ½ÓÊÕµ½ÁË, ²»¹ý²»ÊÇÄãÏëÒªµÄÄÚÈÝ, ÔÙ¿´×Ö·û´®(Êý×é)»¹ÊǿտÕÈ»¡£
É½ÖØË®¸´, µÃÕÒ³ö·²ÅÓÐÁø°µ»¨Ã÷¡£ תת˼ά, ÓÃÁíÒ»ÖÖ×ö·¨°É¡£ÔÚWindowsÖÐ, ÎļþÃûÊDz»Äܺ¬ÓÐ "|,<,>,%...."
µÈÌØÊâ×Ö·ûµÄ.ÓÉÓÚÇ¡ºÃÒª´«µÄÄÚÈÝΪĿ¼×Ö·û´®Êý×é, ËùÒÔ°Ñ×ÖÌõ´®Êý×éתΪ×Ö·ûÊý×é, ÿ¸ö×Ö·û´®ÓÃÒ»¸öÌØÊâ×Ö·û¸ô¿ª¾ÍOKÁË¡£
3. È·±£Á¬Ðø´´½¨Ïß³ÌÕýÈ·ÐÔ
ÓÃÑ»·Óï¾ä´´½¨Ïß³Ì, Èç¹ûûÓÐÒ»¶¨µÄ±£»¤»úÖÆ, ¿Ï¶¨»á³öÊ¡£³ÌÐòÈ磺
int i = paramSettingDlg£®thrTotal //abtain download threads total
for( int j=1;j<=i;j++ )
{
dataPacket.length=j*100+i; // download thread information.
::CreateThread(NULL, 0, ThreadDownload, (LPVOID)&dataPacket, 0, 0);
}
iΪÏÂÔØÏ̵߳Ä×ÜÊý, jΪµ±Ç°Ïß³ÌÐòºÅ£®Ö÷Ïß³ÌÑ»·²»¹ÜCreateThread´´½¨³É¹¦Óë·ñ»¹¼ÌÐøÖ´ÐÐ, µ±ÕæÕýCreateThreadÔÚ´´½¨Ïß³Ìʱ,
jµÄÖµ¿ÉÄÜÒѾ±»ÐÞ¸ÄÁË£®³ÌÐòÐÞ¸ÄÈçÏ£º
for( int j=1;j<=i;j++ )
{
dataPacket.length=j*100+i; // download thread information.
while( ::CreateThread(NULL, 0, ThreadDownload, (LPVOID)&dataPacket, 0, 0) ==0 )
Sleep(30);
}
ÔÚ±¾ÏîÄ¿ÖÐ, ÓõÄÊÇÖÃλ»úÖÆ.Ï̴߳´½¨³É¹¦, ÓÉÏß³ÌÖÃλΪ1, Ö÷Ïß³Ì˯Ñ۵ȴý, ¼ì²âµ½Î»Îª1ʱ, ÔòÖÃλΪ0²¢¼ÌÐø´´½¨Ị̈߳®
4¡¡´ò¿ª¹Ø±ÕÎļþµÄ¿ØÖÆ
¶àÏ̶߳Á/дÎļþÊÇÒ»¼þºÜ»ìÂÒµÄÊÂ, ÓеãÏñÒ»¶ÑÆòؤÇÀ·¹³ÔÄÇÑù£®ËùÒÔÒªÓÐÌõÀí¾ÍҪά»¤ÖÈÐò, Ҫά»¤ÖÈÐò, ×ÔȻҪÎþÉüÐÔÄÜ£®Ã¿´Î¶Á/дÎļþ¶¼Òª¶¨Î»µ½¸Ã°üÄÚÈݶÔÓ¦ÔÎļþµÄλÖÃ.Õâ¸öÓ¦ÓóÌÐòÊÇËø¶¨¶Á/дһ¸ö°üµÄʱ¼ä£®Èç¹ûËø¶¨Õû¸öÏß³Ì, ¼´µÈÒ»¸öÏ̶߳Á/д¸ÃÏß³ÌÓ¦¸Ã¶Á/дµÄ²¿·ÖÔÙ½âËø, ϵͳÐÔÄܱػἱ¾çϽµ, ¾ßÌå²Ù×÷¿ÉÒÔ¿´"³ÌÐòÁ÷³Ìͼ"¡£
ÁíÍâ, Ïß³ÌдÈëµÄÊý¾ÝÒª¼°Ê±Ë¢ÐÂÎļþÁ÷¡£·ñÔò, ³ÌÐòµÈµ½»º³åÇøÂúʱ²ÅÕæÕýдÈëÎļþµÄ, ½á¹û¾ÍÊÇÎļþÂÒÆß°ËÔãÁË¡£
5¡¡Ë«Ñ»·³ÌÐò
Õâ¸öÎÊÌâÊÇÔÚÕâ¸öÏîÄ¿±à³ÌÓöµ½µÄ.˫ѻ·µÄ³ÌÐòÈçÏ£º
CString strArray[6];
char* pChar = "abc1|abc2|abc3|ac";
int len = strlen( "abc1|abc2|abc3|ac" );
int i=0,j=0;
while( i<= len && j<=6 )
{
int k = 0;
while( pChar[i]!='|' )
{
strArray[j].Insert( k, pChar[i] );
i++;
k++;
}
i++;
j++;
}
µ÷ÊÔµÄʱºò, i>len³ÌÐòÏñµÃÁË·èÅ£²¡Ò»Ñù»¹ÊÇÍùǰÅÜ, ²»»áÍ£ÏÂÀ´¡£ÒªÈ·±£ÕýÈ·ÐÔ, ÄÚÑ»·Ó¦¸ÃÐÞ¸ÄÈ磺
while( pChar[i]!='|' && i<=len )
6¡¡ memcpyÔ¤·ÖÅä¿Õ¼ä
ÔÚ³ÌÐòÖжÔÈ«¾Ö±äÁ¿ÒѾ·ÖÅäÁËÒ»´Î¿Õ¼ächar[2000], ÔÚºóÐøµÄʹÓÃÖгÌÐò²»»áÓÐÎÊÌâ, µ«µ±Õû¸ö³ÌÐò¹Ø±Õʱȴð³öÒ»¸öÌáʾ¿ò˵³ÌÐòÓöµ½Ò»¸öÎÊÌâÐèÒª¹Ø±Õ¡£°ÑºóÐøÊ¹ÓÃmemcpy¶ÔÕâ¸ö±äÁ¿¸³ÖµÊ±, Èç¹ûСÓÚ1993¸öchar¿Õ¼ä¾Í²»»á³öÏÖÇ°ÃæËµµ½µÄÌáʾ¿ò¡£
ºóÀ´ÊÔ×ÅÔÚµÚ¶þ´ÎʹÓÃʱÔٴθø¸Ã±äÁ¿·ÖÅäÁËÒ»´Î¿Õ¼ä, Ö®ºóÒ»ÇÐÕý³£ÁË¡£²»ÖªºÎ½â, íûÀ´memcpyµÄÈ·²»Êǰ²È«µÄ¶«Î÷¡£
Èý¡¡ÖØÒª³ÌÐò˵Ã÷£º
1¡¡select I/OÄ£ÐÍ¿ò¼Ü
select I/OÄ£ÐͶÔÓÚ´ó·ÃÎÊÁ¿µÄÍøÂçÌØ±ðÓÐЧ¡£ ÔÚ·þÎñÆ÷¶Ë, ¿ÉÒÔ½¨Á¢¶à¸öÏß³Ì, ÿ¸öÏ̴߳´½¨¿Éͬʱ´´½¨Ò»¸ö¶Áдfd_set¡£ fd_setµÄĬÈÏ´óСΪ64, ¼´ÔÚĬÈϵÄÇé¿öÏÂÒ»¸öSet×î¶à¿ÉÒÔ½ÓÊÜ64¸ösocketµÄÁ¬½Ó¡£
DWORD WINAPI CFileTransSvrView::ThreadSelect(LPVOID lpParameter)
{
// ³õʼ»¯fd_set
SOCKET sListen=(SOCKET)lpParameter;
fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(sListen,&fdSocket);
// ²»¶ÏÑ»·±éÀúfd_set, Èç¹ûijÏîÖÃλ, Ôò±íʾ¸Ãsocket¿ÉÓÃ, Èç¹û״̬ΪÕýÔÚÕìÌý,
// Ôò½¨Á¢Á¬½Ó, ²¢°ÑËü¼ÓÈëµ½fd_setÖÐ, ·ñÔò¾ÍµÈ´ý½ÓÊÕÊý¾Ý¡£selectÓÐ×Ô¶¯»úÖÆ°Ñ²»¿É
//ÓõÄsocket´Ófd_setÖÐɾ³ý¡£
while(TRUE)
{
fd_set fdRead=fdSocket;
int nRet£½::select(0, &fdRead, NULL, NULL, NULL);
if(nRet>0)
{
for(int i£½0;i<(int)fdSocket.fd_count;i++)
{
if(FD_ISSET(fdSocket.fd_array[i],&fdRead))
{
if(fdSocket.fd_array[i] == sListen)
{
sockaddr_in addrRemote;
int nAddrLen=sizeof(addrRemote);
SOCKET sNew£½::accept(sListen,(sockaddr*)&addrRemote,&nAddrLen);
FD_SET(sNew,&fdSocket);
}
else
{
DATA_PACKET recvPacket;
int nRecev£½::recv(fdSocket.fd_array[i], (char*)&recvPacket,
sizeof(recvPacket), 0)¡£
if(nRecev>0)
{
// respond request
}
else
{
::closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], &fdSocket);
}
}
}
}
}
}
return 0;
}
2¡¡ÎļþÏÂÔØº¯Êý
void CFileTransCltView::FillInFile(SOCKET socket, int thrInfo, int packIndex, char* pPackCont)
{
// thrInfoÄ©Á½Î»ÎªÏÂÔØÏß³Ì×ÜÊý,ÔÙÉÏÁ½Î»Îªµ±Ç°Ïß³ÌÐòºÅ
int thrIndex = thrInfo/100; // µ±Ç°Ïß³ÌÐòºÅ
int thrTotal = thrInfo-thrIndex*100; // ÏÂÔØÏ̵߳Ä×ÜÊý
int thrLength = fSize/thrTotal; // µ±Ç°Ïß³ÌÒªÏÂÔØµÄÎļþ³¤¶È
int bPoint = (thrIndex-1)*thrLength; // µ±Ç°Ïß³ÌÒªÏÂÔØµÄÎļþÆðµã
if( thrIndex == thrTotal )
thrLength = fSize-bPoint; // µ±Ç°Ï̵߳ÈÓÚÏß³Ì×ÜÊý,ÔòÖØÐ¸³ÓèÒªÏÂÔØµÄÎÄ //¼þ³¤¶È
FILE *file;
if( (file = fopen( savePath, "ab" )) == NULL )
AfxMessageBox( "Open file occur an error\n" );
// ÿ¸öÏ̶߳¼»áÊÔͼ´ò¿ªÎļþ, Èç¹ûÒÑ´ò¿ª, ·µ»ØÎļþÁ÷Ö¸Õë¡£ ΪʲôÕâÑù£¿ÒòΪ
//ÔÚTCPÏÂÔØÎļþʱ, Ï̵߳İüÊǰ´Ë³ÐòÀ´µÄ, µ«Ïß³ÌÈ´²»Ò»¶¨»á°´Ç°ºó˳ÐòÖ´ÐС£
int packTotal = thrLength/2000 +1;
int subTotal = packTotal;
DATA_PACKET dPacket;
while( subTotal>0 )
{
critSection.Lock(5000);
fseek( file,bPoint+(packIndex-1)*2000,SEEK_SET );
if( packIndex == packTotal ) //the last packet in thread,data maybe less than 2000B
{
int fLength = thrLength-(packTotal-1)*2000;
int errorcode=fwrite( pPackCont,1,fLength,file);
fflush(file);
recvFSize+=fLength;
}
else
{
fwrite( pPackCont,sizeof(char),2000,file );
fflush(file);
recvFSize+=2000;
}
critSection.Unlock();
subTotal££;
if( subTotal>0 )
{
if( recv( socket, (char*)&dPacket, sizeof(dPacket), 0 ) != 0 )
{
packIndex = dPacket.length;
Memcpy( pPackCont, dPacket.content, sizeof(dPacket.content) );
}
}
else
{ // ¸ÃÏß³ÌÏÂÔØÈÎÎñÍê³É, ÅжÏÊÇ·ñÒѾÍêÈ«ÏÂÔØÍêÎļþ, Èç¹ûÊÇÔò¹Ø±Õ
if( recvFSize == fSize )
fclose(file);
return;
}
}
}
3. ¿Í»§¶ËÏ̺߳¯Êý
DWORD WINAPI CFileTransCltView::ThreadRequest(LPVOID lpParameter)
{
DATA_PACKET requestPacket=*(DATA_PACKET*)lpParameter;
SOCKET socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockaddr_in sin;
sin.sin_addr.S_un.S_addr=inet_addr(strIP);
sin.sin_family=AF_INET;
sin.sin_port=htons(1032);
if(::connect(socket,(sockaddr*)&sin,sizeof(sin))!=0)
{
AfxMessageBox("Request failure!");
return 0;
}
int thrInfo;
if( requestPacket.packetType=='D' ) //save download thead infomation for function
// FillInFile()
{
thrInfo=requestPacket.length;
thrFlag=true;
}
::send( socket,(char*)&requestPacket,sizeof(requestPacket),0 );
memset( requestPacket.content,0,sizeof(requestPacket.content) );
if( ::recv(socket,(char*)&requestPacket,sizeof(requestPacket),0) )
{
if( requestPacket.packetType=='r' )
{
int szBuffer=requestPacket.length;
pDrives=new char[2000]; //Make sure that allocate memery!
memcpy(pDrives,requestPacket.content,szBuffer); //Make sure that use memcpy()
}
if(requestPacket.packetType=='d' )
{
pDrives=new char[2000]; // ÔÙ´ÎΪpDrives·ÖÅä¿Õ¼ä²Å²»»á³ö´í
Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) );
/* 2000 will take an error ?????*/
//char's pointer to CString Array
int i=0,j=0;
while( i { for(int k=0; pDrives[i]!='|' && i arrFiles[j].Insert(k,pDrives[i]); i++; j++; } return 0; } if( requestPacket.packetType=='f' ) fSize=requestPacket.length; //Download file if( requestPacket.packetType=='D' ) { //memset( pDrives,0,2000 ); Memcpy( pDrives,requestPacket.content,sizeof(requestPacket.content) ); FillInFile( socket,thrInfo,requestPacket.length,pDrives); } } ::closesocket(socket); return 0; } ËÄ¡¡³ÌÐò½á¹¹Í¼ ¿´±ðÈ˵ijÌÐò¾ø¶Ô²»ÊÇÒ»¼þºÃÊÂ, Òª¿´¸öÃ÷°×¾Í¸üÄÑÁË, ÌØ±ðÊÇûÓÐËã·¨ÃèÊöÉõÖÁÒ»¾ä×¢ÊͶ¼Ã»ÓеijÌÐò¡£ËùÒ԰ѳÌÐòÁ÷³Ìͼ»Á˳öÀ´,ºÃÃ÷°×һЩ¡£ 1. ·þÎñÆ÷¶Ë ·þÎñÆ÷¶ËµÄ´óÖÂÁ÷³Ì¾ÍÊÇÕâÑù, Ïß³ÌÀïÃæ¾ÍÊÇselect(...)¡£²»¹ýÓÐЩÅжϺͳö´í´¦Àíδ»³ö¡£´ÓÉÌÒµ³ÌÐò½Ç¶È¿´À´,ÓÐÁ½µãÊǺÜÖØÒªµÄ, Ò»ÊDz¶»ñÒì³£ºÍ³ö´í´¦Àí, ¶þÊǼò½à¸ßЧ¡£ÎÒÃDZà³ÌÓ¦ÍùÕâ·½Ãæ¿¿Â£¡£ ͼ1 2. ¿Í»§¶Ë ͼ2 3. ¿Í»§¶ËÏß³Ì Í¼3 4. Ë«»÷Ê÷ÏîÄ¿£º ͼ4 5. дÎļþFillInFile ͼ5 £Ñ£Ñ£º£³£µ£¸£¹£¹£¶£µ£¶£¶¡¡




¼¼ÊõÖ§³Ö£º

