• <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>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            TCP/IP編程實(shí)現(xiàn)遠(yuǎn)程文件傳輸


            TCP/IP編程實(shí)現(xiàn)遠(yuǎn)程文件傳輸
            ??
            ????在TCP/IP網(wǎng)絡(luò)結(jié)構(gòu)中,為了保證網(wǎng)絡(luò)安全,網(wǎng)絡(luò)人員往往需要在路由器上添加防火墻,禁止非法用戶用ftp等安全危害較大的TCP/IP協(xié)議訪問主機(jī)。而有時系統(tǒng)維護(hù)人員需要用ftp將一些文件從中心機(jī)房主機(jī)傳到前端網(wǎng)點(diǎn)主機(jī)上,比如應(yīng)用程序的替換升級。如果每次傳輸文件時都要打開防火墻,未免顯得有些繁瑣,要是在自己的應(yīng)用程序中增加一個專門的文件傳輸模塊,那將是十分愉快的事情。
            ?
              UNIX網(wǎng)絡(luò)程序設(shè)計一般都采用套接字(socket)系統(tǒng)調(diào)用。針對目前十分流行的客戶/服務(wù)器模式,其程序編寫步驟如下:
              1.Socket系統(tǒng)調(diào)用
              為了進(jìn)行網(wǎng)絡(luò)I/O,服務(wù)器和客戶機(jī)兩端的UNIX進(jìn)程要做的第一件事是調(diào)用socket()系統(tǒng)調(diào)用,建立軟插座,指明合適的通訊協(xié)議。格式為:
              #include<sys/types.h>
              #include<sys/socket.h>
              int?socket(int?family,int?type,int?protocol)
              其中:(1)family指明套節(jié)字族,其值包括:
              AF_UNIX  ?(UNIX內(nèi)部協(xié)議族)
              AF_INET  ?(Iternet協(xié)議)
              AF_NS?(XeroxNs協(xié)議,TCP/IP編程取該值)
              AF_IMPLINK ?(IMP鏈接層)
              (2)type?指明套接字類型,取值有:
              SOCK_STREAM?    (流套接字)
              SOCK_DGRAM?    (數(shù)據(jù)報套接字)
              SOCK_RAW ?    (原始套接字)
              SOCK_SEQPACKET  ?(定序分組套接字)
              一般情況下,前兩個參數(shù)的組合就可以決定所使用的協(xié)議,這時第三個參數(shù)被置為0,如果第一個參數(shù)為AF_INET,第二個參數(shù)選SOCK_STREAM,則使用的協(xié)議為TCP;第二個參數(shù)選SOCK_DGRAM,則使用的協(xié)議為UDP;當(dāng)?shù)诙€參數(shù)選SOCK_RAW時,使用的協(xié)議為IP。值得指出的是并不是所有的族和類型的組合都是合法的,具體請查閱相關(guān)資料。該系統(tǒng)調(diào)用若成功則返回一個類似文件描述符,成為套節(jié)字描述字,可以像文件描述符那樣用read和write對其進(jìn)行I/O操作。當(dāng)一個進(jìn)程使用完該軟插座時,需用close(<描述符>關(guān)閉(具體見后面內(nèi)容)。
              2.服務(wù)器端Bind系統(tǒng)調(diào)用
              軟插座創(chuàng)建時并沒有與任何地址相關(guān)聯(lián),必須用bind()系統(tǒng)調(diào)用為其建立地址聯(lián)系。其格式為:
              #include<sys/types.h>
              #include<sys/socket.h>
              int?bind(int?socketfd,struct?sockaddr_in?*localaddr,sizeof(localaddr));
              其中:(1)第一個參數(shù)socketfd是前步socket()系統(tǒng)調(diào)用返回的套節(jié)字描述符。
              (2)第二個參數(shù)被捆向本地地址的一種結(jié)構(gòu),該結(jié)構(gòu)在sys/netinet/in.h中定義:
              struct?sockaddr_in{
               short?sin_family;/*socket()系統(tǒng)調(diào)用的協(xié)議族如AF_INET*/
               u_short?sin_port;/*網(wǎng)絡(luò)字節(jié)次序形式的端口號碼*/
               struct?in_addr?sin_addr;/*網(wǎng)絡(luò)字節(jié)次序形式的網(wǎng)絡(luò)地址*/
               char?sin_zero[8];
              }
              一臺機(jī)器上的每個網(wǎng)絡(luò)程序使用一個各自獨(dú)立的端口號碼,例如:telnet程序使用端口號23,而ftp文件傳輸程序使用端口號21。我們在設(shè)計應(yīng)用程序時,端口號碼可以由getservbyname()函數(shù)從/etc/services庫文件中獲取,也可以由htons?(int?portnum)函數(shù)將任意正整數(shù)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)次序形式來得到,有些版本的UNIX操作系統(tǒng)則規(guī)定1024以下的端口號碼只可被超級用戶使用,普通用戶程序使用的端口號碼只限于1025到32767之間。網(wǎng)絡(luò)地址可以由gethostbyname(char*hostname)函數(shù)得到(該函數(shù)和getservbyname()一樣都以網(wǎng)絡(luò)字節(jié)次序形式返回所有在他們結(jié)構(gòu)中的數(shù)據(jù)),參數(shù)hostname為/etc/hosts文件中某一網(wǎng)絡(luò)地址所對應(yīng)的機(jī)器名。該函數(shù)返回一個類型為hostent的結(jié)構(gòu)指針,hostent結(jié)構(gòu)在netdb.h中定義:
              struct?hostent{
              ?char?*h_name;
              ?char?**h_aliases;
              ?int?h_addrtype;
              ?int?h_length;  /*地址長度*/
              ?char?**h_addr_list;
              ?#define?h_addr?h_addr_list[0];/*地址*/
              }
              (3)第三個參數(shù)為第二個結(jié)構(gòu)參數(shù)的長度,如果調(diào)用成功,bind返回0,否則將返回-1并設(shè)置errno。
              3.服務(wù)器端系統(tǒng)調(diào)用listen,使服務(wù)器愿意接受連接
              格式:int?listen(int?socketfd,int?backlong)
              它通常在socket和bind調(diào)用后在accept調(diào)用前執(zhí)行。第二個參數(shù)指明在等待服務(wù)器執(zhí)行accept調(diào)用時系統(tǒng)可以排隊多少個連接要求。此參數(shù)常指定為5,也是目前允許的最大值。
              4.服務(wù)器調(diào)用accept,以等待客戶機(jī)調(diào)用connect進(jìn)行連接。格式如下:
              int?newsocket=(int?socketfd,struct?sockaddr_in?*peer,int*addrlen);
              該調(diào)用取得隊列上的第一個連接請求并建立一個具有與sockfd相同特性的套節(jié)字。如果沒有等待的連接請求,此調(diào)用阻塞調(diào)用者直到一連接請求到達(dá)。連接成功后,該調(diào)用將用對端的地址結(jié)構(gòu)和地址長度填充參數(shù)peer和addlen,如果對客戶端的地址信息不感興趣,這兩個參數(shù)用0代替。
              5.客戶端調(diào)用connect()與服務(wù)器建立連接。格式為:
              connect(int?socketfd,struct?sockaddr_in?*servsddr,int?addrlen)
              客戶端取得套接字描述符后,用該調(diào)用建立與服務(wù)器的連接,參數(shù)socketfd為socket()系統(tǒng)調(diào)用返回的套節(jié)字描述符,第二和第三個參數(shù)是指向目的地址的結(jié)構(gòu)及以字節(jié)計量的目的地址的長度(這里目的地址應(yīng)為服務(wù)器地址)。調(diào)用成功返回0,否則將返回-1并設(shè)置errno。
              6.通過軟插座發(fā)送數(shù)據(jù)
              一旦建立連接,就可以用系統(tǒng)調(diào)用read和write像普通文件那樣向網(wǎng)絡(luò)上發(fā)送和接受數(shù)據(jù)。Read接受三個參數(shù):一個是套節(jié)字描述符;一個為數(shù)據(jù)將被填入的緩沖區(qū),還有一個整數(shù)指明要讀的字節(jié)數(shù),它返回實(shí)際讀入的字節(jié)數(shù),出錯時返回-1,遇到文件尾則返回0。Write也接受三個參數(shù):一個是套節(jié)字描述符;一個為指向需要發(fā)送數(shù)據(jù)的緩沖區(qū),還有一個整數(shù)指明要寫入文件的字節(jié)個數(shù),它返回實(shí)際寫入的字節(jié)數(shù),出錯時返回-1。當(dāng)然,也可以調(diào)用send和recv來對套節(jié)字進(jìn)行讀寫,其調(diào)用與基本的read和write系統(tǒng)調(diào)用相似,只是多了一個發(fā)送方式參數(shù)。
              7.退出程序時,應(yīng)按正常方式關(guān)閉套節(jié)字。格式如下:
              int?close(socketfd)
              前面介紹了UNIX客戶/服務(wù)器模式網(wǎng)絡(luò)編程的基本思路和步驟。值得指出的是socket編程所涉及的系統(tǒng)調(diào)用不屬于基本系統(tǒng)調(diào)用范圍,其函數(shù)原形在libsocket.a文件中,因此,在用cc命令對原程序進(jìn)行編譯時需要帶-lsocket選項。
              現(xiàn)在,我們可以針對文章開頭提出的問題著手進(jìn)行編程了。在圖示的網(wǎng)絡(luò)結(jié)構(gòu)中,為使中心機(jī)房的服務(wù)器能和網(wǎng)點(diǎn)上的客戶機(jī)進(jìn)行通信,需在服務(wù)器端添加通過路由器1112到客戶機(jī)的路由,兩臺客戶機(jī)也必須添加通過路由器2221到服務(wù)器的路由。在服務(wù)器的/etc/hosts文件中應(yīng)該包含下面內(nèi)容:
              1.1.1.1  server
              2.2.2.2  cli1
              2.2.2.3  cli2
              客戶機(jī)的/etc/hosts文件中應(yīng)該有本機(jī)地址信息和服務(wù)器的地址信息,如cli1客戶機(jī)的/etc/hosts文件:
              2.2.2.2  cli1
              1.1.1.1  server
              網(wǎng)絡(luò)環(huán)境搭建好后,我們可以在服務(wù)器端編寫fwq.c程序,負(fù)責(zé)接受客戶機(jī)的連接請求,并將從源文件中讀取的數(shù)據(jù)發(fā)送到客戶機(jī)。客戶機(jī)程序khj.c向服務(wù)器發(fā)送連接請求,接收從服務(wù)器端發(fā)來的數(shù)據(jù),并將接收到的數(shù)據(jù)寫入目標(biāo)文件。源程序如下:
            /*服務(wù)器源程序fwq.c*/?
            #include
            <stdio.h>?
            #include
            <sys/types.h>?
            #include
            <sys/fcntl.h>?
            #include
            <sys/socket.h>?
            #include
            <sys/netinet/in.h>?
            #include
            <netdb.h>?
            #include
            <errno.h>?
            main()?
            {?
              
            char?c,buf[1024],file[30];?
              
            int?fromlen,source;?
              register?
            int?k,s,ns;?
              
            struct?sockaddr_in?sin;?
              
            struct?hostent?*hp;?
              system(″clear″);?
              printf(″\n″);?
              ??
              printf(″\n\n\t\t輸入要傳輸?shù)奈募骸?;?
              scanf(″%s″,file);?
              
            if?((source=open(file,O_RDONLY))<0){?
               perror(″源文件打開出錯″);?
               exit(
            1);?
              }
            ?
              printf(″\n\t\t在傳送文件,稍候…″);?
              hp
            =gethostbyname(″server″);?
              
            if?(hp==NULL){?
              ?perror(″返回主機(jī)地址信息錯
            !!!″);?
              ?exit(
            2);?
              }
            ?
              s
            =socket(AF_INET,SOCK_STREAM,0);?
              
            if(s<0){?
              ?perror(″獲取SOCKET號失敗
            !!!″);?
              ?exit(
            3);?
              }
            ?
              sin.sin_family
            =AF_INET;?
              sin.sin_port
            =htons(1500);/*使用端口1500*/?
              bcopy(hp-
            >h_addr,&sin.sin_addr,hp->h_length);?
              
            if(bind(s,&sin,sizeof(sin))<0){?
               perror(″不能將服務(wù)器地址捆綁到SOCKET號上
            !!!″);?
               colse(s);?
               exit(
            4);?
              }
            ?
              
            if(listen(s,5)<0{?
               perror(″sever:listen″);?
               exit(
            5);?
              }
            ?
            while(1){?
              
            if((ns=accept(s,&sin,&fromlen))<0){?
               perror(″sever:accept″);?
               exit(
            6);?
              }
            ?
              lseek(source,OL,
            0);/*每次接受客戶機(jī)連接,應(yīng)將用于讀的源文件指針移到文件頭*/?
              write(ns,file,
            sizeof(file));?/*發(fā)送文件名*/?
              
            while((k=read(source,buf,sizeof(buf)))>0)?
              ?write(ns,buf,k);?
              printf(″\n\n\t\t傳輸完畢
            !!!\n″);?
              close(ns);?
            }
            ?
              close(source);?
              exit(
            0);?
              
            /*客戶機(jī)源程序khj.c*/?
              #include
            <stdio.h>?
              #include
            <sys/types.h>?
              #include
            <sys/fcntl.h>?
              #include
            <sys/socket.h>?
              #include
            <sys/netinet/in.h>?
              #include
            <netdb.h>?
              #include
            <errno.h>?
              #include?
            <string.h>?
              main()?
              
            {?
               
            char?buf[1024],file[30];?
               
            char?*strs=″\n\n\t\t正在接收文件″;?
               
            int?target;?
               register?
            int?k,s;?
               
            struct?sockaddr_in?sin;?
               
            struct?hostent?*hp;?
               system(″clear″);?
               printf(″\n″);?
               ??
               hp
            =gethostbyname(″server″);?
               
            if(hp==NULL){?
                      perror(″返回服務(wù)器地址信息錯
            !!!″);?
              ? exit(
            1);?
               }
            ?
               s
            =socket(AF_INET,SOCK_STREAM,0);?
               
            if(s<0){?
                perror(″獲取SOCKET號失敗
            !!!″);?
                exit(
            2);?
               }
            ?
               sin.sin_family
            =AF_INET;?
               sin.sin_port
            =htons(1500);/*端口號需與服務(wù)器程序使用的一致*/?
               bcopy(hp-
            >h_addr,&sin.sin_addr,hp->h_length);?
               printf(″\n\n\t\t正在與服務(wù)器連接…″);?
               
            if(connect(s,&sin,sizeof(sin),0)<0){?
                perror(″不能與服務(wù)器連接
            !!!″);?
                exit(
            3);?
               }
            ?
               
            while((k=read(s,file,sizeof(file)))<=0/*接收文件名*/?
              ?
            if((target=open(file,o_WRONLY|O_CREAT|O_TRUNC,0644))<0){?
                perror(″不能打開目標(biāo)文件
            !!″);?
                exit(
            4);?
              }
            ?
              strcat(strs,file);?
              strcat(strs,″,稍候…″);?
              write(
            1,strs,strlen(strs));?
              
            while((k=read(s,buf,sizeof(buf)))>0)?
               write(tatget,buf,k);?
              printf(″\n\n\t\t接收文件成功
            !!!\n″);?
              close(s);?
              close(target);?
              }
            ?

              上述程序在Sco?Unix?System?v3.2及Sco?TCP/IP?Rumtime環(huán)境下調(diào)試通過。

            posted on 2006-04-20 17:16 楊粼波 閱讀(1329) 評論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程

            欧美精品丝袜久久久中文字幕 | 午夜精品久久影院蜜桃| 久久久受www免费人成| 久久亚洲精品无码观看不卡| 午夜精品久久影院蜜桃| 久久综合亚洲鲁鲁五月天| 亚洲色大成网站WWW久久九九| 天天爽天天狠久久久综合麻豆| 激情伊人五月天久久综合| 亚洲国产精品久久久久久| 久久综合久久鬼色| 久久综合综合久久综合| 欧美久久综合性欧美| 婷婷久久综合九色综合绿巨人| 无码国内精品久久人妻| 国产成人精品久久亚洲| 亚洲精品国产综合久久一线| 婷婷综合久久中文字幕蜜桃三电影 | 久久精品成人国产午夜| 久久精品成人影院| 婷婷久久香蕉五月综合加勒比| 国产一区二区精品久久凹凸| 中文字幕久久精品无码| 国产女人aaa级久久久级| 狠狠精品久久久无码中文字幕| 国产成人久久777777| 国产69精品久久久久9999APGF | 久久精品国产99久久久古代| 久久精品国产亚洲综合色| 久久国产精品无| 大香网伊人久久综合网2020| 日韩精品久久久久久久电影蜜臀| 国产精品熟女福利久久AV| 日韩AV无码久久一区二区| 无码任你躁久久久久久久| 国产精品久久久久久久久免费| 久久笫一福利免费导航 | 青青青青久久精品国产| 久久精品国产亚洲AV忘忧草18| 国内精品久久久久久久亚洲| 99999久久久久久亚洲|