青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-250  評(píng)論-20  文章-55  trackbacks-0

在如今的網(wǎng)絡(luò)應(yīng)用中,文件的傳送是重要的功能之一,也是共享的基礎(chǔ)。一些重要的協(xié)議像HTTP,F(xiàn)TP等都支持文件的傳送。尤其是FTP,它的全稱就是“文件傳送協(xié)議”,當(dāng)初的工程師設(shè)計(jì)這一協(xié)議就是為了解決網(wǎng)絡(luò)間的文件傳送問(wèn)題,而且以其穩(wěn)定,高速,簡(jiǎn)單而一直保持著很大的生命力。作為一個(gè)程序員,使用這些現(xiàn)有的協(xié)議傳送文件相當(dāng)簡(jiǎn)單,不過(guò),它們只適用于服務(wù)器模式中。這樣,當(dāng)我們想在點(diǎn)與點(diǎn)之間傳送文件就不適用了或相當(dāng)麻煩,有一種大刀小用的意味。筆者一直想尋求一種簡(jiǎn)單有效,且具備多線程斷點(diǎn)續(xù)傳的方法來(lái)實(shí)現(xiàn)點(diǎn)與點(diǎn)之間的文件傳送問(wèn)題,經(jīng)過(guò)大量的翻閱資料與測(cè)試,終于實(shí)現(xiàn)了,現(xiàn)把它共享出來(lái),與大家分享。
我寫了一個(gè)以此為基礎(chǔ)的實(shí)用程序(網(wǎng)絡(luò)傳圣,包含源代碼),可用了基于TCP/IP的電腦上,供大家學(xué)習(xí)。


(本文源代碼運(yùn)行效果圖)


實(shí)現(xiàn)方法(VC++,基于TCP/IP協(xié)議)如下:
仍釆用服務(wù)器與客戶模式,需分別對(duì)其設(shè)計(jì)與編程。
服務(wù)器端較簡(jiǎn)單,主要就是加入待傳文件,監(jiān)聽客戶,和傳送文件。而那些斷點(diǎn)續(xù)傳的功能,以及文件的管理都放在客戶端上。

一、服務(wù)器端

首先介紹服務(wù)器端:
最開始我們要定義一個(gè)簡(jiǎn)單的協(xié)議,也就是定義一個(gè)服務(wù)器端與客戶端聽得懂的語(yǔ)言。而為了把問(wèn)題簡(jiǎn)化,我就讓服務(wù)器只要聽懂兩句話,一就是客戶說(shuō)“我要讀文件信息”,二就是“我準(zhǔn)備好了,可以傳文件了”。
由于要實(shí)現(xiàn)多線程,必須把功能獨(dú)立出來(lái),且包裝成線程,首先建一個(gè)監(jiān)聽線程,主要負(fù)責(zé)接入客戶,并啟動(dòng)另一個(gè)客戶線程。我用VC++實(shí)現(xiàn)如下:

DWORD WINAPI listenthread(LPVOID lpparam)
{
//由主函數(shù)傳來(lái)的套接字
  SOCKET  pthis=(SOCKET)lpparam;
//開始監(jiān)聽
int rc=listen(pthis,30);
//如果錯(cuò)就顯示信息
if(rc<0){
CString aaa;
aaa="listen錯(cuò)誤\n";
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
aaa.ReleaseBuffer();
return 0;
}
//進(jìn)入循環(huán),并接收到來(lái)的套接字
while(1){
//新建一個(gè)套接字,用于客戶端
SOCKET s1;
s1=accept(pthis,NULL,NULL);
   //給主函數(shù)發(fā)有人聯(lián)入消息
CString aa;
aa="一人聯(lián)入!\n";
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aa.GetBuffer(0),1);
aa.ReleaseBuffer();
DWORD dwthread;
//建立用戶線程
::CreateThread(NULL,0,clientthread,(LPVOID)s1,0,&dwthread);
}
return 0;
}
接著我們來(lái)看用戶線程:
先看文件消息類定義
struct fileinfo
{
int fileno;//文件號(hào)
int type;//客戶端想說(shuō)什么(前面那兩句話,用1,2表示)
long len;//文件長(zhǎng)度
int seek;//文件開始位置,用于多線程
char name[100];//文件名
};
用戶線程函數(shù):
DWORD WINAPI clientthread(LPVOID lpparam)
{
//文件消息
fileinfo* fiinfo;
//接收緩存
char* m_buf;
m_buf=new char[100];
//監(jiān)聽函數(shù)傳來(lái)的用戶套接字
SOCKET  pthis=(SOCKET)lpparam;
//讀傳來(lái)的信息
int aa=readn(pthis,m_buf,100);
//如果有錯(cuò)就返回
if(aa<0){
closesocket (pthis);
return -1;
}
//把傳來(lái)的信息轉(zhuǎn)為定義的文件信息
fiinfo=(fileinfo*)m_buf;
CString aaa;
//檢驗(yàn)客戶想說(shuō)什么
switch(fiinfo->type)
{
//我要讀文件信息
case 0:
//讀文件
aa=sendn(pthis,(char*)zmfile,1080);
//有錯(cuò)
if(aa<0){
closesocket (pthis);
return -1;
}
//發(fā)消息給主函數(shù)
aaa="收到LIST命令\n";
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
break;
//我準(zhǔn)備好了,可以傳文件了
case 2:
//發(fā)文件消息給主函數(shù)
aaa.Format("%s  文件被請(qǐng)求!%s\n",zmfile[fiinfo->fileno].name,nameph[fiinfo->fileno]);
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
//讀文件,并傳送
readfile(pthis,fiinfo->seek,fiinfo->len,fiinfo->fileno);
//聽不懂你說(shuō)什么
default:
aaa="接收協(xié)議錯(cuò)誤!\n";
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
break;
}
return 0;
}
讀文件函數(shù)
void readfile(SOCKET  so,int seek,int len,int fino)
{
//文件名
CString myname;
myname.Format("%s",nameph[fino]);
CFile myFile;
//打開文件
myFile.Open(myname, CFile::modeRead | CFile::typeBinary|CFile::shareDenyNone);
//傳到指定位置 
myFile.Seek(seek,CFile::begin);
char m_buf[SIZE];
int len2;
int len1;
len1=len;
//開始接收,直到發(fā)完整個(gè)文件
while(len1>0){
len2=len>SIZE?SIZE:len;
myFile.Read(m_buf, len2);
int aa=sendn(so,m_buf,len2);
if(aa<0){
closesocket (so);
break;
}
len1=len1-aa;
len=len-aa;
}
myFile.Close();
}

服務(wù)器端最要的功能各技術(shù)就是這些,下面介紹客戶端。

二、客戶端

客戶端最重要,也最復(fù)雜,它負(fù)責(zé)線程的管理,進(jìn)度的記錄等工作。

大概流程如下:
先連接服務(wù)器,接著發(fā)送命令1(給我文件信息),其中包括文件長(zhǎng)度,名字等,然后根據(jù)長(zhǎng)度決定分幾個(gè)線程下載,并初使化下載進(jìn)程,接著發(fā)送命令2(可以給我傳文件了),并記錄文件進(jìn)程。最后,收尾。
這其中有一個(gè)十分重要的類,就是cdownload類,定義如下:

class cdownload
{
public:
void createthread();//開線程
DWORD finish1();//完成線程
int sendlist();//發(fā)命令1
downinfo doinfo;//文件信息(與服務(wù)器定義一樣)
int startask(int n);開始傳文件n
long m_index;
BOOL good[BLACK];
int  filerange[100];
CString fname;
CString fnametwo;
UINT threadfunc(long index);//下載進(jìn)程
int sendrequest(int n);//發(fā)文件信息
cdownload(int thno1);
virtual ~cdownload();
};
下面先介紹sendrequest(int n),在開始前,向服務(wù)器發(fā)獲得文件消息命令,以便讓客戶端知道有哪些文件可傳
int cdownload::sendrequest(int n)
{
//建套接字
sockaddr_in local;
SOCKET m_socket;
int rc=0;
//初使化服務(wù)器地址
local.sin_family=AF_INET;
local.sin_port=htons(1028);
local.sin_addr.S_un.S_addr=inet_addr(ip);
m_socket=socket(AF_INET,SOCK_STREAM,0);
int ret;
//聯(lián)接服務(wù)器
ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local));
//有錯(cuò)的話
if(ret<0){
AfxMessageBox("聯(lián)接錯(cuò)誤");
closesocket(m_socket);
return -1;
}
//初使化命令
fileinfo fileinfo1;
fileinfo1.len=n;
fileinfo1.seek=50;
fileinfo1.type=1;
//發(fā)送命令
int aa=sendn(m_socket,(char*)&fileinfo1,100);
if(aa<0){
closesocket(m_socket);
return -1;
}
//接收服務(wù)器傳來(lái)的信息
aa=readn(m_socket,(char*)&fileinfo1,100);
if(aa<0){
closesocket(m_socket);
return -1;
}
//關(guān)閉
shutdown(m_socket,2);
closesocket(m_socket);
return 1;
}
有了文件消息后我們就可以下載文件了。在主函數(shù)中,用法如下:
//下載第clno個(gè)文件,并為它建一個(gè)新cdownload類
down[clno]=new cdownload(clno);
//開始下載,并初使化
type=down[clno]->startask(clno);
//建立各線程
createthread(clno);
下面介紹開始方法:
//開始方法
int cdownload::startask(int n)
{
//讀入文件長(zhǎng)度
doinfo.filelen=zmfile[n].length;
//讀入名字
fname=zmfile[n].name;
CString tmep;
//初使化文件名
tmep.Format("\\temp\\%s",fname);
//給主函數(shù)發(fā)消息
CString aaa;
aaa="正在讀取 "+fname+" 信息,馬上開始下載。。。\n";
AfxGetMainWnd()->SendMessageToDescendants(WM_AGE1,(LPARAM)aaa.GetBuffer(0),1);
aaa.ReleaseBuffer();
//如果文件長(zhǎng)度小于0就返回
if(doinfo.filelen<=0) return -1;
//建一個(gè)以.down結(jié)尾的文件記錄文件信息
CString m_temp;
m_temp=fname+".down";
doinfo.name=m_temp;
FILE* fp=NULL;
CFile myfile;
//如果是第一次下載文件,初使化各記錄文件
if((fp=fopen(m_temp,"r"))==NULL){
filerange[0]=0;
//文件分塊
for(int i=0;i<BLACK;i++)
{
if(i>0)
filerange[i*2]=i*(doinfo.filelen/BLACK+1);
filerange[i*2+1]=doinfo.filelen/BLACK+1;
}
filerange[BLACK*2-1]=doinfo.filelen-filerange[BLACK*2-2];
myfile.Open(m_temp,CFile::modeCreate|CFile::modeWrite | CFile::typeBinary);
//寫入文件長(zhǎng)度
myfile.Write(&doinfo.filelen,sizeof(int));
myfile.Close();
 
CString temp;
for(int ii=0;ii<BLACK;ii++){
//初使化各進(jìn)程記錄文件信息(以.downN結(jié)尾)
temp.Format(".down%d",ii);
m_temp=fname+temp;
myfile.Open(m_temp,CFile::modeCreate|CFile::modeWrite | CFile::typeBinary);
//寫入各進(jìn)程文件信息
myfile.Write(&filerange[ii*2],sizeof(int));
myfile.Write(&filerange[ii*2+1],sizeof(int));
myfile.Close();
}
((CMainFrame*)::AfxGetMainWnd())->m_work.m_ListCtrl->AddItemtwo(n,2,0,0,0,doinfo.threadno);
}
else{
//如果文件已存在,說(shuō)明是續(xù)傳,讀上次信息
CString temp;
 
m_temp=fname+".down0";
if((fp=fopen(m_temp,"r"))==NULL)
return 1;
else fclose(fp);
int bb;
bb=0;
//讀各進(jìn)程記錄的信息
for(int ii=0;ii<BLACK;ii++)
{
temp.Format(".down%d",ii);
m_temp=fname+temp;
 
myfile.Open(m_temp,CFile::modeRead | CFile::typeBinary);
myfile.Read(&filerange[ii*2],sizeof(int));
myfile.Read(&filerange[ii*2+1],sizeof(int));
myfile.Close();
bb = bb+filerange[ii*2+1];
CString temp;
}
if(bb==0) return 1;
doinfo.totle=doinfo.filelen-bb;
 
((CMainFrame*)::AfxGetMainWnd())->m_work.m_ListCtrl->AddItemtwo(n,2,doinfo.totle,1,0,doinfo.threadno);
}
 	//建立下載結(jié)束進(jìn)程timethread,以管現(xiàn)各進(jìn)程結(jié)束時(shí)間。
DWORD dwthread;
::CreateThread(NULL,0,timethread,(LPVOID)this,0,&dwthread);
return 0;
}
下面介紹建立各進(jìn)程函數(shù),很簡(jiǎn)單:
void CMainFrame::createthread(int threadno)
{
DWORD dwthread;
//建立BLACK個(gè)進(jìn)程
for(int i=0;i<BLACK;i++)
{
m_thread[threadno][i]=	::CreateThread(NULL,0,downthread,(LPVOID)down[threadno],0,&dwthread);
}
}
downthread進(jìn)程函數(shù)
DWORD WINAPI downthread(LPVOID lpparam)
{
cdownload* pthis=(cdownload*)lpparam;
//進(jìn)程引索+1
InterlockedIncrement(&pthis->m_index);
//執(zhí)行下載進(jìn)程
pthis->threadfunc(pthis->m_index-1);
return 1;
}
下面介紹下載進(jìn)程函數(shù),最最核心的東西了
UINT cdownload::threadfunc(long index)
{
//初使化聯(lián)接
sockaddr_in local;
SOCKET m_socket;
int rc=0;
 
local.sin_family=AF_INET;
local.sin_port=htons(1028);
local.sin_addr.S_un.S_addr=inet_addr(ip);
m_socket=socket(AF_INET,SOCK_STREAM,0);
int ret;
//讀入緩存
char* m_buf=new char[SIZE];
int re,len2;
fileinfo fileinfo1;
//聯(lián)接
ret=connect(m_socket,(LPSOCKADDR)&local,sizeof(local));
//讀入各進(jìn)程的下載信息
fileinfo1.len=filerange[index*2+1];
fileinfo1.seek=filerange[index*2];
fileinfo1.type=2;
fileinfo1.fileno=doinfo.threadno;
 
re=fileinfo1.len;
 
//打開文件 
CFile destFile;
FILE* fp=NULL;
//是第一次傳的話
if((fp=fopen(fname,"r"))==NULL)
destFile.Open(fname, CFile::modeCreate|CFile::modeWrite | CFile::typeBinary|CFile::shareDenyNone);
else
//如果文件存在,是續(xù)傳
destFile.Open(fname,CFile::modeWrite | CFile::typeBinary|CFile::shareDenyNone);
//文件指針移到指定位置
destFile.Seek(filerange[index*2],CFile::begin);
//發(fā)消息給服務(wù)器,可以傳文件了
sendn(m_socket,(char*)&fileinfo1,100);
CFile myfile;
CString temp;
temp.Format(".down%d",index);
m_temp=fname+temp;
 	//當(dāng)各段長(zhǎng)度還不為0時(shí)
while(re>0){
len2=re>SIZE?SIZE:re;
 
//讀各段內(nèi)容
int len1=readn(m_socket,m_buf,len2);
//有錯(cuò)的話
if(len1<0){
closesocket(m_socket);
break;
}
 
//寫入文件
destFile.Write(m_buf, len1);
//更改記錄進(jìn)度信息
filerange[index*2+1]-=len1;
filerange[index*2]+=len1;
//移動(dòng)記錄文件指針到頭
myfile.Seek(0,CFile::begin);
//寫入記錄進(jìn)度
myfile.Write(&filerange[index*2],sizeof(int));
myfile.Write(&filerange[index*2+1],sizeof(int));
//減去這次讀的長(zhǎng)度
re=re-len1;
//加文件長(zhǎng)度
doinfo.totle=doinfo.totle+len1;
};
//這塊下載完成,收尾
 
myfile.Close();
destFile.Close();
delete [] m_buf;
shutdown(m_socket,2);
 
 
if(re<=0) good[index]=TRUE;
return 1;
}

到這客戶端的主要模塊和機(jī)制已基本介紹完。希望好好體會(huì)一下這種多線程斷點(diǎn)續(xù)傳的方法。

posted on 2007-04-20 15:18 jay 閱讀(466) 評(píng)論(0)  編輯 收藏 引用 所屬分類: socket
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            红桃视频国产精品| 亚洲视频第一页| 亚洲日韩欧美视频一区| 免费成人激情视频| 一道本一区二区| 欧美激情一区二区| 欧美成年视频| 国产精品v欧美精品v日韩精品| 在线中文字幕一区| 蜜臀av性久久久久蜜臀aⅴ| 久久爱另类一区二区小说| 久久综合伊人77777| 欧美在线看片| 亚洲美女av黄| 久久永久免费| 久久视频这里只有精品| 久久国产成人| 国产情人综合久久777777| 久久精品视频在线观看| 久久综合九色99| 亚洲电影毛片| 久久久国产一区二区三区| 国产精品美女久久久久久2018| 激情亚洲网站| 亚洲国产精品国自产拍av秋霞| 国产精品久久久久久久9999| 美国成人毛片| 亚洲啪啪91| 亚洲一级电影| 狼狼综合久久久久综合网| 亚洲精品视频在线| 久久精品卡一| 国产精品青草久久久久福利99| 亚洲福利一区| 午夜精品久久久久久久久久久久久| 久久午夜精品一区二区| 一本久久青青| 欧美国产日韩a欧美在线观看| 国产日韩欧美不卡在线| 亚洲视频 欧洲视频| 亚洲欧美日韩一区| 日韩视频免费| 欧美成人一品| 欧美中文字幕视频| 欧美日韩黄色一区二区| 狠狠色综合网| 欧美一区二视频| 中国成人亚色综合网站| 欧美日韩国产一级| 亚洲精品少妇30p| 免费国产一区二区| 欧美在线一区二区| 国产欧美一区二区色老头| 亚洲一区在线播放| 一本色道久久综合亚洲精品小说| 欧美成人a视频| 亚洲欧洲一二三| 欧美激情视频网站| 久久精品噜噜噜成人av农村| 国产视频亚洲| 久久夜色撩人精品| 久久爱www.| 亚洲成人在线网| 欧美国产日产韩国视频| 欧美成人一品| 老司机精品福利视频| 亚洲电影免费| 欧美黄色免费| 午夜精品久久久久久99热| 亚洲综合欧美日韩| 一本色道久久99精品综合| 欧美国产在线电影| 免费亚洲电影| 最新国产乱人伦偷精品免费网站| 欧美高清视频一二三区| 欧美国产日韩精品| 亚洲美女视频在线免费观看| 久久国产欧美| 久久三级视频| 亚洲国产精品久久久久秋霞蜜臀 | 亚洲人成久久| 欧美精品久久久久久久久老牛影院| 亚洲三级视频在线观看| 亚洲第一在线综合在线| 欧美日韩国产在线播放网站| 午夜影视日本亚洲欧洲精品| 久久精品一区二区三区不卡牛牛 | 欧美日韩久久| 一区二区三区波多野结衣在线观看| 亚洲美女免费视频| 欧美性猛交99久久久久99按摩| 亚洲免费伊人电影在线观看av| 小嫩嫩精品导航| 亚洲日本va午夜在线电影| 亚洲精品在线观看免费| 国产久一道中文一区| 欧美成人激情视频| 国产精品国产精品| 欧美国产日韩一区二区| 国产精品视区| 亚洲国产精品高清久久久| 欧美系列一区| 免费观看亚洲视频大全| 国产精品亚洲综合一区在线观看 | 亚洲欧美综合| 日韩一二三区视频| 久久久久www| 午夜国产一区| 欧美日韩国产天堂| 久久精品99国产精品| 欧美乱在线观看| 欧美gay视频| 国产亚洲欧美色| 亚洲一区www| 亚洲精品一区在线| 久久久久一区二区| 久久综合久久久久88| 欧美日韩国产综合视频在线观看中文| 性久久久久久久久久久久| 欧美fxxxxxx另类| 久久夜色精品| 国产欧美午夜| 亚洲欧美卡通另类91av| 在线性视频日韩欧美| 欧美大片免费观看在线观看网站推荐 | 欧美一级一区| 亚洲高清资源| 国产精品人人做人人爽| 国产日韩精品在线播放| 亚洲少妇最新在线视频| 日韩午夜激情| 久久综合伊人77777麻豆| 久久亚洲精品中文字幕冲田杏梨| 欧美日韩一区二区欧美激情 | 亚洲一区二区毛片| 欧美日本亚洲韩国国产| 亚洲黄色一区二区三区| 伊人精品视频| 久久久久久久网| 麻豆精品一区二区av白丝在线| 国产在线播精品第三| 久久成人精品无人区| 久久伊人精品天天| 亚洲国产精品久久久久秋霞不卡| 免播放器亚洲一区| 亚洲国产一区二区三区高清| 一区二区日韩伦理片| 欧美日韩亚洲一区在线观看| 99国产精品| 久久av资源网| 在线免费日韩片| 欧美黄污视频| 这里只有精品丝袜| 久久久www成人免费无遮挡大片| 国产午夜亚洲精品不卡| 久久久久国色av免费观看性色| 欧美国产亚洲精品久久久8v| 亚洲视频电影图片偷拍一区| 国产精品一级在线| 久久影院午夜论| 99re66热这里只有精品4| 午夜久久福利| 亚洲电影在线播放| 久久久xxx| 亚洲欧美激情视频在线观看一区二区三区| 欧美在线国产精品| 亚洲第一区中文99精品| 欧美人交a欧美精品| 亚洲自拍偷拍麻豆| 欧美成人影音| 亚洲欧美日韩在线高清直播| 国产网站欧美日韩免费精品在线观看 | 国产视频一区二区三区在线观看| 久久久蜜桃精品| 一区二区国产在线观看| 六月婷婷久久| 亚洲男人的天堂在线| 久久激五月天综合精品| 一区二区在线看| 欧美精品国产一区| 欧美一区亚洲二区| 日韩视频专区| 欧美国产三区| 久久精品国产亚洲精品| 一本色道久久综合| 黑人巨大精品欧美一区二区小视频 | 老巨人导航500精品| 亚洲视屏一区| 亚洲国产日韩欧美在线99| 欧美一区二区三区精品| 亚洲免费av片| 黄色一区二区在线观看| 国产精品欧美一区喷水| 欧美色中文字幕| 国产精品久久二区| 亚洲一区二区影院| 一本久久a久久免费精品不卡| 欧美a级在线| 欧美大片在线观看| 老司机久久99久久精品播放免费|