﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-细心!用心!耐心!-文章分类-服务器编程</title><link>http://www.blogjava.net/jesson2005/category/19576.html</link><description>吾非文人，乃市井一俗人也，读百卷书，跨江河千里，故申城一游； 
一两滴辛酸，三四年学业，五六点粗墨，七八笔买卖，九十道人情。</description><language>zh-cn</language><lastBuildDate>Thu, 22 Nov 2007 19:55:22 GMT</lastBuildDate><pubDate>Thu, 22 Nov 2007 19:55:22 GMT</pubDate><ttl>60</ttl><item><title>利用设计模式提高SOAP服务的运行效率</title><link>http://www.blogjava.net/jesson2005/articles/153282.html</link><dc:creator>张金鹏</dc:creator><author>张金鹏</author><pubDate>Tue, 16 Oct 2007 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/jesson2005/articles/153282.html</guid><wfw:comment>http://www.blogjava.net/jesson2005/comments/153282.html</wfw:comment><comments>http://www.blogjava.net/jesson2005/articles/153282.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jesson2005/comments/commentRss/153282.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jesson2005/services/trackbacks/153282.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Web服务的客户端缓冲技术的设计与实现            利用设计模式提高SOAP服务的运行效率                                                                                                                        ...&nbsp;&nbsp;<a href='http://www.blogjava.net/jesson2005/articles/153282.html'>阅读全文</a><img src ="http://www.blogjava.net/jesson2005/aggbug/153282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jesson2005/" target="_blank">张金鹏</a> 2007-10-16 15:30 <a href="http://www.blogjava.net/jesson2005/articles/153282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FTP菜鳥必看簡易實用教程</title><link>http://www.blogjava.net/jesson2005/articles/128450.html</link><dc:creator>张金鹏</dc:creator><author>张金鹏</author><pubDate>Thu, 05 Jul 2007 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/jesson2005/articles/128450.html</guid><wfw:comment>http://www.blogjava.net/jesson2005/comments/128450.html</wfw:comment><comments>http://www.blogjava.net/jesson2005/articles/128450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jesson2005/comments/commentRss/128450.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jesson2005/services/trackbacks/128450.html</trackback:ping><description><![CDATA[FTP菜鳥必看簡易實用教程<br><br>很多人看到一些長篇的FTP教程會沒什麼耐心看下去,現在就簡明得介紹一下,一看就明的方式希望能好些.還有一些發帖的FTP格式,第四點,新手必須看看了!<br><br>1.FTP概述<br>文件傳輸是指將文件從一台計算機上發送到另一台計算機上，傳輸的文件可以包括電子報表、聲音、編譯後的程序以及字處理程序的文檔文件。<br><br>2.FTP中的兩種工作方式<br>A.Standard模式 FTP的客戶端發送 PORT 命令到FTPserver (PORT模式)<br>B.Passive模式FTP的客戶端發送 PASV命令到 FTP Server (PASV模式) <br><br>3. 怎樣把PASV模式改為PORT模式？<br>CuteFtp<br>請點擊---編輯----全局設置----連接類型----選擇PORT或PASV---然後確定。<br>flashfxp<br>選項---參數設置----防火牆/代理/標識----把使用被動模式前的小勾取消即可<br>leapftp<br>站點管理器－----你要連接的站點－----高級－--去掉pasv前面的勾<br><br>4.<a href="ftp://A:B@c:D/" target=_blank><font color=#0000ff>ftp://A:B@C:D</font></a> 形式的說明<br>A代表用戶名<br>B代表密碼<br>C代表 FTP 地址或者 IP 地址<br>D代表端口---------省略表示默認端口 21 <br><br>5.為什麼FTP連接進去是空的，看不到文件？<br>原因1：不支持PASV，請用 PORT模式。<br>原因2：網站不支持list命令，找到具體的鏈接，用flashget下載<br><br>6.FTP 常見錯誤及解決方法<br><br>421錯誤：同時連接該ftp的人數過多，超出FTP設置的人數了，請等人少的時候再連接。<br><br>530「not login"：<br>用戶名或密碼錯誤，獲得正確的密碼重新連接。<br><br>「連接超時，無法連接」錯誤：該ftp暫時關機，可能是服務器重新啟動，或者FTP進行維護，等FTP正常再連接。<br><br>「無法解析域名」：<br>原因1：該ftp的域名輸入錯誤，如漏打一個字母，使用了全角標點等。<br>解決方法：去發佈該ftp論壇找到正確的域名輸入。<br>原因2：本地的域名解析服務器壞了（是指你的網絡服務商的域名解析服務）<br>解決方法：等本地網絡修好即可使用，也可以直接輸入ftp的ip地址。<br>原因3：該ftp修改了域名。<br>解決方法：去發佈該ftp論壇找正確的域名。<br><br>「only one &#8230;&#8230; ip address&#8230;&#8230;」<br>原因1：使用多線程下載，超過該ftp允許的線程。<br>解決方法：看看自己是不是已經與該ftp有了連接，如果有了就不要再開新的連接。<br>原因2：局域網內有其他人連接了該ftp（長城寬帶等fttb容易出現）<br>解決方法：等幾個小時，別人斷開後，再連接該ftp。<br><br>「連接拒絕」：恭喜你，你的ip已經被該ftp封了。<br>解決方法：等一段時間（由該ftp設定，半小時到一天不等），才能連接該ftp。<br>如果你的ip地址是動態的話，也可以斷開網絡，重播上網連接FTP試試。<br><br>425 ：不能打開數據連接，你可以嘗試用PORT模式來代替PASV模式，或者反之。<br><br>550 No such file or directory：文件可能已經改名或者刪除了<br><br>Not connet,access deny拒絕連接訪問錯誤：不能匿名登錄和訪問，你必須提供用戶名和密碼才能登錄。<br><br>426：關閉連接，中止傳輸 。FTP 可能正在重新啟動，或者服務器維護而關閉。<br><br>FTP口令：<br>文件傳輸軟件的使用格式為：FTP ，如果連接成功，系統將提示用戶輸入用戶名以及口令：<br>LOGIN：（輸入合法的用戶名或者「ANONYMOUS」）<br>PASSWORD：（輸入合法的口令，若以「ANONYMOUS」方式登錄，一般不用口令）<br><br>進入想要連接的FTP站點後，用戶就可以進行相應的文件傳輸操作了，其中一些重要的命令及相似的命令如下：<br>（1）HELP、？、RHELP、REMOTEHELP<br>HELP 顯示LOCAL端的命令說明，若不接受則顯示所有可用命令；<br>？ 相當於HELP，例如：？ CD；<br>RHELP 同HELP，只是它用來顯示REMOTE端的命令說明；<br>REMOTEHELP 相當於RHELP。<br><br>（2）ASC（ASCII）、BIN（BINARY）、IMAGE、TYPE<br>ASCII 切換傳輸模式為文字模式（只能用來傳送DOC文件，因為是7-BIT）<br>BINARY 切換傳輸模式為二進制模式（除文字文件外皆用此模式）；<br>IMAGE 相當於BINARY；<br>TYPE 讓你更改或顯示目前傳輸模式。<br><br>（3）BYE、QUIT<br>BYE 退出FTP；<br>QUIT 相當於BYE。<br><br>（4）CD、CDUP、LCD、PWD、！<br>CD 改變當前工作目錄，例如：CD \PUB;<br>CDUP 回到上一層目錄，相當於你打CD..；<br>LCD 讓你更改或顯示LOCAL端的工作目錄，例如：LCD \TMP;<br>PWD 顯示目前的工作目錄（REMOTE端）；<br>！ 讓你執行外殼命令，例如： ！LS。<br><br>（5）DELETE、MDELETE、RENAME<br>DELETE 刪除REMOTE端的文件<br>MDELETE 批量刪除文件，需配合？或*；<br>RENAME 更改REMOTE端的文件名。<br><br>（6）GET、MGET、PUT、MPUT、RECV、SEND<br>GET 下傳文件；<br>MGET 批量下傳文件，需配合萬用字元，例如：MGET *.GZ;<br>PUT 上傳文件；<br>MPUT 批量上傳文件，需配合萬用字元；<br>RECV 相當於GET（RECV為RECEIVE的簡寫）；<br>SEND 相當於PUT。<br><br>（7）HASH、PROMPT、VERBOSE、STATUS、BELL<br>HASH 切換#字號的出現，每一個#字號表示傳送了1024/8192 BYTES；<br>PROMPT 切換INTERACTIVE ON/OFF；<br>VERBOSE 切換所有文件傳輸過程的顯示；<br>STATUS 顯示目前的一些參數；<br>BELL 當指令做完時會發出一聲叫聲。<br><br>（8）LS、DIR、MLS、MDIR、MKDIR、RMDIR<br>LS 有點像UNIX下的LS（LIST）命令；<br>DIR 相當於LS -L（LIST-LONG）；<br>MLS 只是將遠端某目錄下的文件存於LOCAL端的某文件裡；<br>MDIR 相當於MLS；<br>MKDIR 象DOS下的MD（創建子目錄）一樣；<br>RMDIR 象DOS下的RD（刪除子目錄）一樣；<br><br>（9）OPEN、CLOSE、DISCONNECT、USER<br>OPEN 連接某個遠端FTP服務器；<br>CLOSE 關閉目前的連接；<br>DISCONNECT 相當於CLOSE；<br>USER 再輸入一次用戶名和口令（有點像UNIX下的SU）。<br><br>PASV和PORT模式有什麼不同，為什麼PORT方式比PASV方式安全？<br>FTP傳輸過程中要求建立一個專門的連接來傳輸數據，建立連接有兩個方法：<br>一個就是FTP Server打開一個端口，Client可以去連接這個端口來建立連接。這就是PASV方式。<br>一個就是FTP Client打開一個端口，Server去連接這個端口來建立連接。這就是PORT方式。<br>顯然，如果服務器打開了一個端口，就意味著向互聯網打開了一個端口。所以PORT方式比PASV方式安全
<img src ="http://www.blogjava.net/jesson2005/aggbug/128450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jesson2005/" target="_blank">张金鹏</a> 2007-07-05 22:28 <a href="http://www.blogjava.net/jesson2005/articles/128450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaBean实现多个文件上传的两种方法</title><link>http://www.blogjava.net/jesson2005/articles/128448.html</link><dc:creator>张金鹏</dc:creator><author>张金鹏</author><pubDate>Thu, 05 Jul 2007 14:19:00 GMT</pubDate><guid>http://www.blogjava.net/jesson2005/articles/128448.html</guid><wfw:comment>http://www.blogjava.net/jesson2005/comments/128448.html</wfw:comment><comments>http://www.blogjava.net/jesson2005/articles/128448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jesson2005/comments/commentRss/128448.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jesson2005/services/trackbacks/128448.html</trackback:ping><description><![CDATA[<h1><strong>JavaBean实现多个文件上传的两种方法</strong></h1>
<br>创建：2005-10-28 00:08:45<br>作者：Unlinux<br>来自: http://www.Unlinux.com<br><br><font class=f14 id=zoom><font color=#000000><br>摘要：本文介绍了JavaBean实现多个文件上传的两种方法，分别是使用http协议和ftp协议实现。首先讲述了http协议传送多个文件的基本格式和实现上传的详细过程，之后简单介绍了使用ftpclient 类实现了ftp方式的上传，最后对这两种方法进行了比较。<br>关键字：JavaBean 、http 、ftp 、ftpclient<br>JavaBean是一种基于Java的软件组件。JSP对于在Web?应用中集成JavaBean组件提供了完善的支持。这种支持不仅能缩短开发时间（可以直接利用经测试和可信任的已有组件，避免了重复开发），也为JSP应用带来了更多的可伸缩性。<br>文件的上传功能在基于B/S的开发模式中非常普遍。同其他开发工具相比较，JSP对文件的上传支持并不是很完美，它既不象ASP那样一定需要使用组件来完成，也不像PHP那样直接提供了文件上载的支持。JSP实现文件上传的实现方式是这样的：使用ServletRequest类的getInputStream()方法获得一个客户端向服务器发出的数据流，然后处理这个数据流，从中分析、得到文件上传中传递到服务器的各个参数和数据，然后将其中的文件数据存储为一个文件或插入到数据库中。通常JSP页面中不处理文件的上传功能，而是把这些功能放到Servlet 或JavaBean中去实现。使用Servlet完成文件上传的例子在一些JSP的相关书籍中都有所介绍，我这里介绍使用JeanBean是如何完成文件上传的。JSP中实现文件的上传可以采用两种方式即采用HTTP协议和FTP协议实现，二者在传输的原理上存在很大的差异。以下将结合源代码对它们的实现做简单介绍，相信读者会从中有所收获。以下程序已经调试通过。调试的环境：window 2000 server+Apache +tomcat4.0，JavaBean调试环境：JDK1.4+Editplus。<br>在JSP中使用JavaBean实现基于Web的文件上传功能一般需要三种文件结合完成。这三种文件分别是提供界面的HTML页面文件、完成调用实现上传功能的JavaBean的JSP文件和实现JavaBean的Java的类文件。以下我将重点讲述采用HTTP协议和FTP协议实现文件上传功能的JavaBean部分。<br>1 采用HTTP协议实现多个文件的上传<br>在过去的Html中，表单不能实现文件的上传，这多少限制了一些网页的功能。RFC1867规范（即Html中实现基于表单的文件上传）对表单作出了扩展，增加了一个表单元素〈input type＝file＞。通过使用这个元素，浏览器会自动生成一个输入框和一个按钮，输入框可供用户填写本地的文件名和路径名，按钮可以让浏览器打开一个文件选择框供用户选择文件。具体的表单实现如下：<br>&lt;FORMMETHOD="POST" ACTION="*.jsp" ENCTYPE="multipart/form-data"&gt;<br>&lt;INPUT TYPE="FILE" NAME="FILE1" SIZE="50"&gt;<br>&lt;INPUT TYPE="SUBMIT" VALUE="Upload"&gt;<br>&lt;/FORM&gt;<br>当选择了粘贴文件后就直接输入本地文件的绝对路径，表单的action属性值是*.jsp，这意味着请求（包括上载的文件）将发送给*..jsp文件。在这个过程中实际上就实现了HTTP方式的文件上载。文件从客户端到服务器的上载是由HTTP协议的通用网关界面(CGI)支持的。这种上载方式要求浏览器和WEBServer两方面都能够支持Rfc1867。JavaBean 通过ServletRequest类的getInputStream()方法获得一个客户端向服务器发出的数据流、分析上传的文件格式，根据分析结果将多个文件依次输出服务器端的目标文件中。本例中的JavaBeande的功能是由testUpload类具体实现。TestUpload类的框架如下：<br>public class testUpload<br>{<br>public testUpload(){&#8230;&#8230;}<br>public final void initialize(ServletConfig config) throws ServletException<br>{ m_application = config.getServletContext(); }<br>public void upload() throws testUploadException, IOException, ServletException<br>{&#8230;&#8230;&#8230;}<br>private void getDataSection(){&#8230;&#8230;&#8230;}<br>private void getDataHeader(){&#8230;&#8230;&#8230;}<br>public int save (String destPathName)<br>throws SmartUploadException, IOException, ServletException<br>{&#8230;&#8230;&#8230;}<br>&#8230;&#8230;<br>}<br>通过initialize（）方法初始化Servlet的运行环境。使用upload()方法获得输入流，并分析上传文件的格式，并将各个上传文件的属性赋给多个File类实例处理，这些File类实例由Files类管理。File类根据各文件的属性调用它的save ()方法将多个文件依次输出服务器端的目标文件中。其中upload()方法是关键，用于分析http1.1协议传送文件的格式。经过测试，我们得出传输流文件的格式，这对理解upload()方法很有用。例如，上传我的文档 t.txt文件。格式如下：<br>//文件分隔符<br>-----------------------------7d226137250336 <br>//文件信息头<br>Content-Disposition: form-data; name="FILE1"; filename="C:Documents and SettingsAdministrator.TIMBER-4O6B0ZZ0My Documents t.sql"<br>Content-Type: text/plain<br>//源文件内容 <br>create table info(<br>content image null);<br>//下一个文件的分隔符<br>-----------------------------7d226137250336<br>Content-Disposition: form-data; name="FILE2"; filename=""<br>Content-Type: application/octet-stream<br>-----------------------------7d226137250336<br>从以上文件我们可以看出，HTTP协议在上传多个文件时，是将文件全部放到输入流并以一定的分隔符来区分的。实际上upload()方法就是要分析上面的文件，确定分隔符的内容、各个文件的内容格式、文件的完整路径名称、及其文件的实际数据的始末位置。这里需要说明的一点是分隔符是随机的，它是传输流文件的第一个回车符之前的所有字符。<br>Upload()方法的实现流程是：首先将输入流文件输出到字节数组m_binArray中，通过下面的代码实现。<br>m_totalBytes=1024；totalRead=0；<br>for(; totalRead &lt; m_totalBytes; totalRead += readBytes)<br>try<br>{ m_request.getInputStream();<br>readBytes = m_request.getInputStream().read(m_binArray, totalRead, m_totalBytes - totalRead);<br>}catch(Exception e){ throw new SmartUploadException("Unable to upload.");}<br>这里采用了循环中多字节读取方法，以上循环不断地读取数据直到数组填满为止。如果一个文件可以完全得到，则文件的所有字节也就可以全部得到。但是因为网络速度通常比CPU慢得多，所以程序很容易在所有的数据到来之前就清空网络缓冲区。实际上，多字节读取方法在试图从暂时为空但是开放的网络缓存区读取数据时，该方法会返回0，这表示没有数据存在但网络流没有关闭。这种情况下，单字节方法将阻止运行程序的执行，所以多字节的行为优于单字节read()方法的行为。接下来将分析字节数组m_binArray。首先找到分隔符；使用getDataHeader()方法返回文件信息头的值，从中确定源文件的完整路径名、源文件的扩展名和源文件文件内容格式；使用getDataSection()方法返回文件的内容数据，并记录文件数据在字节数组中的起止位置。然后生成一个File类实例，并将文件的完整路径名、源文件的扩展名、源文件文件内容格式和文件的内容数据的起止位置放到File类实例的属性中。找到下一个分隔符，继续重复上述过程，直至分析完毕。<br>2 采用FTP协议实现多个文件的上传<br>FTP协议是Internet上用来传送文件的协议，规定了Internet上文件互相传送的标准。在java中实现这一功能是借助FtpClient类完成的。具体实现过程：首先与FTP服务器建立连接；初始化文件的传输方式，包括ASCII和BINARY两种方式；将文件输出到文件输入流FileInputStream中；FileInputStream中的数据读入字节数组中；字节数组中的数据写入输出流TelnetOutputStream（利用write方法将数据写入到一个网络链接上）。这样和源文件同名的一个文件就复制到了服务器端。本例的JavaBean中通过connectServer()、upload()和closeConnect()三个方法完成文件上传过程。主要实现如下：<br>public class ftpUpload<br>{ String filename;String filename1;FtpClient ftpClient;<br>public void connectServer(string server,string user,string password,string path)<br>{<br>//server：FTP服务器的IP地址；user:登录FTP服务器的用户名<br>//password：登录FTP服务器的用户名的口令；path：FTP服务器上的路径<br>try{ ftpClient=new FtpClient();<br>ftpClient.openServer(server);<br>ftpClient.login(user, password);<br>System.out.println("login success!");<br>if (path.length()!=0) ftpClient.cd(path);<br>ftpClient.binary(); }catch (IOException ex) {System.out.println(ex);}<br>}<br>public void closeConnect()<br>{try{ ftpClient.closeServer();<br>}catch (IOException ex) {System.out.println(ex);}<br>}<br>public void upload() <br>{ filename1=findFileName(filename);<br>//从filename中分析出文件的名称，作为目标文件的名称,具体方法实现未给出<br>try {<br>TelnetOutputStream os=ftpClient.put(filename1);<br>java.io.File file_in=new java.io.File(filename);<br>FileInputStream is=new FileInputStream(file_in);<br>byte[] bytes=new byte[1024];<br>int c;<br>while ((c=is.read(bytes))!=-1){ os.write(bytes,0,c); }<br>is.close(); os.close();<br>} catch (IOException ex) {System.out.println(ex);}<br>}<br>}<br>connectServer()完成与FTP服务器建立连接的功能，使用FtpClient的openServer(string server)方法打开远程FTP服务器,然后使用FtpClient的login(user, password)方法登录服务器。登录远程FTP服务器有两种方式，一种是注册用户登录，另一种是以匿名方式登录。前者要求用户首先注册为服务器的客户，服务器会给客户一个登录账号和密码，依据账号和密码连结到服务器上。后者要求用户不用注册而使用特殊的用户名"annoymous"和"guest"有限制的访问远程主机的公开文件，现在许多系统要求用户将Email地址作为口令。出于安全的目的，大部分匿名FTP主机一般只允许远程用户下载文件，而不允许上传，这将依赖于FTP服务器的设置。用户可根据实际情况选择使用两种方式。登录完成后使用FtpClient的binary()方法初始化传输方式为字节方式。upload()完成文件的上传功能。创建源文件的文件输入流FileInputStream,将输入流写入到字节数组中，利用TelnetOutputStream的write方法将字节数组中的数据写入到一个网络链接上。由于TelnetOutputStream打开的是FTP服务器上的一个文件，所以数据写入到了目标文件中，这样就完成了文件上传。closeConnect()要求与服务器断开连接。<br>以上只是单个文件上传的过程，如果是多个文件可以多次调用此上传过程。由以上两种方式我们可以看出采用FTP协议实现多个文件的上传比较简单，容易实现。利用FTP协议上传文件一般是编写的客户端的程序，服务器端的安全设置会比较复杂；而利用HTTP协议上传文件则是服务器端的应用程序，相对来说安全设置会比较简单。并且通过测试发现FTP上传方式在传输大文件时速度是HTTP上传方式的几十倍甚至几百倍，但在传输小于1M的文件时却比HTTP上传方式稍慢一些。所以说两种传输方式各有优势，请读者根据自身情况量力而行。如果有什么问题或者是需要其他部分的源码，请与我联系！<br><br>参考文献：<br>廖若雪，《Jsp高级编程》，机械工业出版社，2001.3<br>黄理、洪亮等，《Jsp高级编程》，北京希望电子出版社，2001.10<br>Elliotte Rusty Harold著，刘东华、王巍、唐刚译，Java网络编程,中国电力出版社，2001.8<br>Bruce Eckel著，京京工作室译，Java编程思想,机械工业出版社，1999.4<br>http://www.jspsmart.com</font></font>
<img src ="http://www.blogjava.net/jesson2005/aggbug/128448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jesson2005/" target="_blank">张金鹏</a> 2007-07-05 22:19 <a href="http://www.blogjava.net/jesson2005/articles/128448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的网络编程：用Java实现FTP服务器  </title><link>http://www.blogjava.net/jesson2005/articles/128447.html</link><dc:creator>张金鹏</dc:creator><author>张金鹏</author><pubDate>Thu, 05 Jul 2007 14:18:00 GMT</pubDate><guid>http://www.blogjava.net/jesson2005/articles/128447.html</guid><wfw:comment>http://www.blogjava.net/jesson2005/comments/128447.html</wfw:comment><comments>http://www.blogjava.net/jesson2005/articles/128447.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jesson2005/comments/commentRss/128447.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jesson2005/services/trackbacks/128447.html</trackback:ping><description><![CDATA[<table width="100%">
    <tbody>
        <tr>
            <td align=middle><strong><font size=3>Java的网络编程：用Java实现FTP服务器</font></strong> </td>
        </tr>
        <tr>
            <td align=middle>关键字：不详 </td>
        </tr>
    </tbody>
</table>
<table width="97%" align=center>
    <tbody>
        <tr>
            <td><font class=b1>FTP(File Transfer Protocol 文件传输协议)是Internet 上用来传送文件的协议。在Internet上通过FTP 服务器可以进行文件的上传(Upload)或下载(Download)。FTP是实时联机服务，在使用它之前必须是具有该服务的一个用户(用户名和口令)，工作时客户端必须先登录到作为服务器一方的计算机上，用户登录后可以进行文件搜索和文件传送等有关操作，如改变当前工作目录、列文件目录、设置传输参数及传送文件等。使用FTP可以传送所有类型的文件，如文本文件、二进制可执行文件、图象文件、声音文件和数据压缩文件等。
            <p>&#160;</p>
            <p><br>FTP 命令 </p>
            <p><br>FTP 的主要操作都是基于各种命令基础之上的。常用的命令有： </p>
            <p>◆ 设置传输模式，它包括ASCⅡ(文本) 和BINARY 二进制模式; </p>
            <p>◆ 目录操作，改变或显示远程计算机的当前目录(cd、dir/ls 命令); </p>
            <p>◆ 连接操作，open命令用于建立同远程计算机的连接；close命令用于关闭连接; </p>
            <p>◆ 发送操作，put命令用于传送文件到远程计算机；mput 命令用于传送多个文件到远程计算机; </p>
            <p>◆ 获取操作，get命令用于接收一个文件；mget命令用于接收多个文件。 </p>
            <p><br>编程思路 </p>
            <p><br>根据FTP 的工作原理，在主函数中建立一个服务器套接字端口，等待客户端请求，一旦客户端请求被接受，服务器程序就建立一个服务器分线程，处理客户端的命令。如果客户端需要和服务器端进行文件的传输，则建立一个新的套接字连接来完成文件的操作。 </p>
            <p><br>编程技巧说明 </p>
            <p><br>1.主函数设计 </p>
            <p>在主函数中，完成服务器端口的侦听和服务线程的创建。我们利用一个静态字符串变量initDir 来保存服务器线程运行时所在的工作目录。服务器的初始工作目录是由程序运行时用户输入的，缺省为C盘的根目录。 </p>
            <p>具体的代码如下： </p>
            <p>public class ftpServer extends Thread{ <br>private Socket socketClient; <br>private int counter; <br>private static String initDir; <br>public static void main(String[] args){ <br>if(args.length != 0) { <br>initDir = args[0]; <br>}else{ initDir = "c:";} <br>int i = 1; <br>try{ <br>System.out.println("ftp server started!"); <br>//监听21号端口 <br>ServerSocket s = new ServerSocket(21); <br>for(;;){ <br>//接受客户端请求 <br>Socket incoming = s.accept(); <br>//创建服务线程 <br>new ftpServer(incoming,i).start(); <br>i++; <br>} <br>}catch(Exception e){} <br>} <br></p>
            <p><br>2. 线程类的设计 </p>
            <p>线程类的主要设计都是在run()方法中实现。用run()方法得到客户端的套接字信息，根据套接字得到输入流和输出流，向客户端发送欢迎信息。 </p>
            <p>3. FTP 命令的处理 </p>
            <p>(1) 访问控制命令 </p>
            <p>◆ user name(user) 和 password (pass) 命令处理代码如下： </p>
            <p>if(str.startsWith("USER")){ <br>user = str.substring(4); <br>user = user.trim(); <br>out.println("331 Password");} <br>if(str.startsWith("PASS")) <br>out.println("230 User "+user+" logged in."); <br></p>
            <p><br>User 命令和 Password 命令分别用来提交客户端用户输入的用户名和口令。 </p>
            <p>◆ CWD (CHANGE WORKING DIRECTORY) 命令处理代码如下： </p>
            <p>if(str.startsWith("CWD")){ <br>String str1 = str.substring(3); <br>dir = dir+"/"+str1.trim(); <br>out.println("250 CWD command succesful"); <br>} <br></p>
            <p><br>该命令改变工作目录到用户指定的目录。 </p>
            <p>◆ CDUP (CHANGE TO PARENT DIRECTORY) 命令处理代码如下： </p>
            <p>if(str.startsWith("CDUP")){ <br>int n = dir.lastIndexOf("/"); <br>dir = dir.substring(0,n); <br>out.println("250 CWD command succesful"); <br>} <br></p>
            <p><br>该命令改变当前目录为上一层目录。 </p>
            <p>◆ QUIT命令处理代码如下： </p>
            <p>if(str.startsWith("QUIT")) { <br>out.println("GOOD BYE"); <br>done = true; <br>} <br></p>
            <p><br>该命令退出及关闭与服务器的连接，输出GOOD BYE。 </p>
            <p>(2) 传输参数命令 </p>
            <p>◆ Port命令处理代码如下： </p>
            <p>if(str.startsWith("PORT")) { <br>out.println("200 PORT command successful"); <br>int i = str.length() - 1; <br>int j = str.lastIndexOf(","); <br>int k = str.lastIndexOf(",",j-1); <br>String str1,str2; <br>str1=""; <br>str2=""; <br>for(int l=k+1;l&lt;j;l++){ <br>str1 = str2 + str.charAt(l); <br>} <br>for(int l=j+1;l&lt;=i;l++){ <br>str2 = str2 + str.charAt(l); <br>} <br>tempPort = Integer.parseInt(str1) * 16 *16 +Integer.parseInt(str2); <br>} <br></p>
            <p><br>使用该命令时，客户端必须发送客户端用于接收数据的32位IP 地址和16位 的TCP 端口号。这些信息以8位为一组，使用十进制传输，中间用逗号隔开。 </p>
            <p>◆ TYPE命令处理代码如下： </p>
            <p>if(str.startsWith("TYPE")){ <br>out.println("200 type set"); <br>} <br></p>
            <p><br>TYPE 命令用来完成类型设置。 </p>
            <p>(3) FTP 服务命令 </p>
            <p>◆ RETR (RETEIEVE) 和 STORE (STORE)命令处理的代码 </p>
            <p>if(str.startsWith("RETR")){ <br>out.println("150 Binary data connection"); <br>str = str.substring(4); <br>str = str.trim(); <br>RandomAccessFile outFile = new <br>RandomAccessFile(dir+"/"+str,"r"); <br>Socket tempSocket = new Socket(host,tempPort); <br>OutputStream outSocket <br>= tempSocket.getOutputStream(); <br>byte byteBuffer[]= new byte[1024]; <br>int amount; <br>try{ <br>while((amount = outFile.read(byteBuffer)) != -1){ <br>outSocket.write(byteBuffer, 0, amount); <br>} <br>outSocket.close(); <br>out.println("226 transfer complete"); <br>outFile.close(); <br>tempSocket.close(); <br>} <br>catch(IOException e){} <br>} <br>if(str.startsWith("STOR")){ <br>out.println("150 Binary data connection"); <br>str = str.substring(4); <br>str = str.trim(); <br>RandomAccessFile inFile = new <br>RandomAccessFile(dir+"/"+str,"rw"); <br>Socket tempSocket = new Socket(host,tempPort); <br>InputStream inSocket <br>= tempSocket.getInputStream(); <br>byte byteBuffer[] = new byte[1024]; <br>int amount; <br>try{ <br>while((amount =inSocket.read(byteBuffer) )!= -1){ <br>inFile.write(byteBuffer, 0, amount); <br>} <br>inSocket.close(); <br>out.println("226 transfer complete"); <br>inFile.close(); <br>tempSocket.close(); <br>} <br>catch(IOException e){} <br>} <br></p>
            <p><br>文件传输命令包括从服务器中获得文件RETR和向服务器中发送文件STOR，这两个命令的处理非常类似。处理RETR命令时，首先得到用户要获得的文件的名称，根据名称创建一个文件输入流，然后和客户端建立临时套接字连接，并得到一个输出流。随后，将文件输入流中的数据读出并借助于套接字输出流发送到客户端，传输完毕以后，关闭流和临时套接字。 </p>
            <p>STOR 命令的处理也是同样的过程，只是方向正好相反。 </p>
            <p>◆ DELE (DELETE)命令处理代码如下： </p>
            <p>if(str.startsWith("DELE")){ <br>str = str.substring(4); <br>str = str.trim(); <br>File file = new File(dir,str); <br>boolean del = file.delete(); <br>out.println("250 delete command successful"); <br>} <br></p>
            <p><br>DELE 命令用于删除服务器上的指定文件。 </p>
            <p>◆ LIST命令处理代码如下： </p>
            <p>if(str.startsWith("LIST")) { <br>try{ <br>out.println("150 ASCII data"); <br>Socket tempSocket = new Socket(host,tempPort); <br>PrintWriter out2= new PrintWriter(tempSocket.getOutputStream(),true); <br>File file = new File(dir); <br>String[] dirStructure = new String[10]; <br>dirStructure= file.list(); <br>String strType=""; <br>for(int i=0;i&lt;dirStructure.length;i++){ <br>if( dirStructure[i].indexOf(".") == -1) { <br>strType = "d ";} <br>else <br>{strType = "- ";} <br>out2.println(strType+dirStructure[i]); <br>} <br>tempSocket.close(); <br>out.println("226 transfer complete"); <br>} <br>catch(IOException e){} <br></p>
            <p><br>LIST 命令用于向客户端返回服务器中工作目录下的目录结构，包括文件和目录的列表。处理这个命令时，先创建一个临时的套接字向客户端发送目录信息。这个套接字的目的端口号缺省为1，然后为当前工作目录创建File 对象，利用该对象的list()方法得到一个包含该目录下所有文件和子目录名称的字符串数组，然后根据名称中是否含有文件名中特有的&#8220;.&#8221;来区别目录和文件。最后，将得到的名称数组通过临时套接字发送到客户端。 <br></font></p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/jesson2005/aggbug/128447.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jesson2005/" target="_blank">张金鹏</a> 2007-07-05 22:18 <a href="http://www.blogjava.net/jesson2005/articles/128447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>