TCP 통신을 기반으로 완료된 Java 소켓 프로토콜을 기반으로 한 파일 전송의 전체 예입니다.
TCP 기반 바이너리 파일 전송 외에도 Java Swing, 데모 프로그램의 일부 프로그래밍 기술
주요 기능은 다음과 같이 구현됩니다.
먼저 전체 돔 수업 간의 관계를 살펴 보겠습니다.
다음은 위 그림에 따라 각 클래스의 기능 및 코드 구현에 대한 자세한 설명입니다.
서버 측 :
Filetransferserver 클래스의 기능은 먼저 포트 9999에서 서버 소켓을 생성하는 것입니다.
연결을 듣기 시작하십시오. 관련 코드는 다음과 같습니다.
private void statherver (int port) {try {serversocket = new serversocket (port); System.out.println ( "포트에서 시작된 서버 :" + 포트); while (true) {socket client = serversocket.accept (); // 소득 소켓 시스템 차단 및 대기 중. out.println ( "그냥 연결된" + client.getRemotesocketAddress ()); filereceivetask task = new Filereceivetask (클라이언트); bar.setValue (0); // wask.addpropertychangelistener (new PropertyChangelistener () {public void propertyChange (propublic void propertyChange (propertyChangeEvent evt)) {if ( "progress".Equals (evt.getPropertyName ())) {bar.setValue ((Integer) evt.getNewValue ()); task.execute (); }} catch (ioexception e) {e.printstacktrace (); }}PropertyChangelistener에 대해 Java는 Bean 모델의 데이터 변경을 모니터링하는 매우 강력한 도구 클래스를 제공합니다. 프로그램은
Swingworker의 진행 속성 값 변경 이벤트 캡처를 변경 한 다음 Jprogressbar 업데이트
인스턴스 객체, UI의 새로 고침을 실현합니다. filetransferserver 클래스의 전체 소스 코드는 다음과 같습니다.
패키지 com.gloomyfish.socket.tutorial.filetransfer; java.awt.borderlayout import; java.awt.flowlayout 가져 오기; import java.awt.event.actionevent; import java.awt.event.actionListener; java.beans.propertychangeevent import; java.beans.propertychangelistener import; import java.io.ioexception; import java.net.serversocket; import java.net.socket; import javax.swing.boxlayout; import javax.swing.jbutton; import javax.swing.jframe; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jprogressbar; Public Class Filetransferserver는 JFrame 구현 ActionListener { / ** * * / public final static String start_svr = "start"; 공개 최종 정적 문자열 shut_down_svr = "종료"; 공개 최종 정적 문자열 end_flag = "eof"; 개인 정적 최종 최종 긴 SerialversionUID = 1L; 개인 서버 소켓 서사 소켓; 개인 JBUTTON STARTBTN; 개인 Jprogressbar 바; public filetransferserver () {super ( "파일 서버"); initComponent (); setuplistener (); } private void setUplistener () {startBtn.addactionListener (this); } private void initComponent () {startBtn = new JButton (start_svr); jpanel progresspanel = new jpanel (); ProgressPanel.setLayout (New BoxLayout (ProgressPanel, BoxLayout.y_axis)); bar = new jprogressbar (); bar.setminimum (0); bar.setmaximum (100); ProgressPanel.add (bar); getContentPane (). SetLayout (New BorderLayout ()); JPANEL BTNPANEL = NEW JPANEL (New FlowLayout (FlowLayout.right)); btnpanel.add (startbtn); getContentPane (). Add (btnpanel, borderlayout.south); getContentPane (). Add (ProgressPanel, BorderLayout.Center); } private void startingerver (int port) {try {serversocket = new Serversocket (포트); System.out.println ( "포트에서 시작된 서버 :" + 포트); while (true) {socket client = serversocket.accept (); // 소득 소켓 시스템 차단 및 대기 중. out.println ( "그냥 연결된" + client.getRemotesocketAddress ()); filereceivetask task = new Filereceivetask (클라이언트); bar.setValue (0); // wask.addpropertychangelistener (new PropertyChangelistener () {public void propertyChange (propublic void propertyChange (propertyChangeEvent evt)) {if ( "progress".Equals (evt.getPropertyName ())) {bar.setValue ((Integer) evt.getNewValue ()); task.execute (); }} catch (ioexception e) {e.printstacktrace (); }} public void showuccess () {bar.setValue (100); joptionpane.showmessagedialog (이것은 "파일이 성공적으로 수신되었습니다!"); } @Override public void actionPerformed (actionEvent e) {if (start_svr.equals (e.getActionCommand ())) {스레드 startThread = new Thread (new runnable () {public void run () {startserver (9999);}}); startThread.start (); startBtn.setenabled (false); } else if (shut_down_svr.equals (e.getActionCommand ())) {} else {// do nody ...}} public static void main (String [] args) {FipleTranSferserver Server = new FiletranSferserver (); Server.SetDefaultCloseOperation (jframe.exit_on_close); Server.SetSize (400, 400); Server.SetResizable (False); Server.SetVisible (true); }} FilereCeivetask는 서버 측의 파일 수락 클래스입니다.
먼저 설정된 TCP 스트림에서 파일 이름과 파일 크기를 가져온 다음 파일 콘텐츠 수락 바이트 수락을 시작합니다.
생성 된 파일 개체 스트림에 쓰고 마지막으로 파일 크기가 서면 바이트 스트림과 동일인지 확인합니다.
마지막으로 파일 전송이 완료되고 TCP 스트림이 닫힐 수 있음을 상대방에게 알리기 위해 파일 발신자에게 메시지를 보내십시오.
이 클래스의 전체 소스 코드는 다음과 같습니다.
패키지 com.gloomyfish.socket.tutorial.filetransfer; import java.io.bufferedOutputStream; import java.io.bufferedOutputStream; import java.io.datainputstream; import java.io.file; import java.io.fileoutputStream; import java.io.outputStreamwriter; import java.net.socket; javax.swing.swingworker import; Public Class Filereceivetask는 Swingworker <Integer, Object> {private socket _msocket; public filereceivetask (소켓 클라이언트) {this._msocket = client; } @override Protected Integer doinbackground ()는 예외를 겪고 {// 파일 메타 정보 get meta information datainputstream input = new DatainputStream (_msocket.getInputStream ()); 문자열 filename = input.readutf (); int filelength = (int) input.readlong (); // 총 바이트 수 파일 파일 = 새 파일 ( "C : // user // fish // downloads" + file.separator + filename); BufferedOutputStream output = 새 BufferedOutputStream (새 파일 OutputStream (파일)); System.out.println ( "수신 파일 이름 =" + filename); System.out.println ( "수신 파일 크기 =" + filelength/1024 + "KB"); // 파일의 내용을 받기 시작하고 byte [] content = new Byte [2048]; int 오프셋 = 0; int numreadbytes = 0; while (Offset <fileLength && (numReadBytes = input.read (content))> 0) {output.write (content, 0, numreadbytes); float precent = 100.0f * ((플로트) 오프셋)/((float) filelengrength); setProgress ((int) precent); 오프셋 += NumReadBytes; } system.out.println ( "numreadbytes =" + numreadbytes); if (offset <filelength) {numreadbytes = input.read (content); System.out.println ( "numreadbytes =" + numreadbytes); System.out.println ( "서버 측 파일 콘텐츠 오류"); } else {system.out.println ( "파일 수신 작업이 올바르게 수행되었습니다"); } setProgress (100); // 클라이언트에게 지금 소켓을 닫으라고 말하면 이미 파일을 성공적으로 수신합니다 !! BufferedWriter BufferedWriter = New BufferedWriter (New OutputStreamWriter (_msocket.getoutPutStream ()); BufferedWriter.write ( "done/r/n"); BufferedWriter.flush (); // 파일 및 소켓 output.close ()를 닫습니다. _msocket.close (); 반환 100; }} 고객:
Filetransferclient는 서버에 대한 연결을 구현 한 다음 선택하는 클라이언트 UI 클래스입니다.
전송할 파일 (이미지, PDF, 워드 문서 등). 그렇지 않다면
서버 정보를 입력하면 프롬프트가 나타납니다. 포트는 9999로 명시되어 있습니다
[파일 보내기] 버튼이 파일 선택 상자를 엽니 다. 사용자가 전송할 파일을 선택한 후
Filetransfertask 스레드 및 파일 전송 실행을 시작합니다. 클라이언트 UI 코드는 다음과 같습니다.
패키지 com.gloomyfish.socket.tutorial.filetransfer; java.awt.borderlayout import; java.awt.flowlayout 가져 오기; import java.awt.gridlayout; import java.awt.event.actionevent; import java.awt.event.actionListener; java.beans.propertychangeevent import; java.beans.propertychangelistener import; import java.io.file; import java.net.inetSocketAddress; import java.net.socketAddress; import javax.swing.borderfactory; import javax.swing.boxlayout; import javax.swing.jbutton; import javax.swing.jfilechooser; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jprogressbar; import javax.swing.jtextfield; /*** 나는 보통 영어 댓글을 작성하고 때로는 중국어 의견도 쓴다. 그러나 영어* 댓글을 작성하는 것이 코드와 더 통합되어 있다고 생각합니다. */ public class filetransferclient 확장 jframe 구현 ActionListener {/ ** * */ private static final long serialversionuid = 1L; 공개 최종 정적 문자열 send_cmd = "파일 보내기"; 공개 최종 정적 int 최소 = 0; 공개 최종 정적 int 최대 = 100; // public final static string connect_cmd = "Connect"; 개인 Jbutton sendfilebtn; 개인 Jtextfield Serverfield; 개인 Jtextfield Portfield; 개인 Jprogressbar 바; public filetransferclient () {super ( "파일 전송 클라이언트"); initcomponents (); } private void initcomponents () {getContentPane (). setLayout (new BorderLayout ()); jpanel progresspanel = new jpanel (); ProgressPanel.setLayout (New BoxLayout (ProgressPanel, BoxLayout.y_axis); bar = bar = new jprogressbar (); progresspanel.add (bar); bar.setminimum (최소); arecimum); Gridlayout (2,2,5,5); serversettingpanel.add ( "서버 포트 :"); btnpanel.add (sendfilebtn). @ActionEvent e) {string 명령 = e status = showopendialog (null); AddPropertyChangelistener (New PropertyChangelistener () {public void PropertyChange (Progress " Execution}} else {// do nothing}} public void showsuccess () {bar.setValue.showMessagedIalog (파일은 성공적으로 보내기!) {return serverfield.getText (); integer.gettext (). port.length (port) {integer.parseint (port); Client.SetFaultCloseOperation (Jframe.exit_on_close); Filetransfertask에서 구현 한 주요 기능은 다음과 같습니다.
이 클래스의 전체 소스 코드는 다음과 같습니다.
패키지 com.gloomyfish.socket.tutorial.filetransfer; import java.io.bufferedInputStream; import java.io.bufferedReader; import java.io.datainputstream; import java.io.dataOutputStream; import java.io.file; import java.io.fileInputStream; import java.io.ioexception; import java.io.inputStreamReader; import java.net.socket; import java.net.socketAddress; javax.swing.swingworker import; Public Class Filetransfertask는 Swingworker <Integer, Object> {개인 파일 SelectedFile; 개인 소켓 MSocket; 비공개 소켓 드레스 주소; 비공개 filetransferclient 부모; public filetransfertask (파일 파일, Socketaddress 주소, Filetransferclient 소유자 /*, Jprogressbar 진행* /) {this.address = address; this.SelectedFile = 파일; msocket = new Socket (); this.parent = 소유자; } @override Protected Integer doinbackground ()는 예외를 던집니다. {// 파일의 크기를 가져옵니다. 긴 길이 = selectedFile.length (); if (length> integer.max_value) {wrach new ioException ( "파일을 완전히 읽을 수 없음" + selectedFile.getName () + "너무 길다 (" + length + "bytes, max 지원" + integer.max_value + "); } msocket.connect (주소); // 파일 데이터를 고정하기 위해 바이트 배열을 만듭니다 .SetSolinger (True, 60); dataOutputStream dout = new DataOutputStream (msocket.getOutputStream ()); // 이제 파일 메타 정보를 보내기 시작합니다. dout.writeUtf (selectedFile.getName ()); dout.writelong (길이); dout.flush (); // end comment filedatapackage pdata = new FiledAtapackage (); DatainputStream은 = new DatainputStream (new FileInputStream (selectedFile)); 바이트 [] 바이트 = 새로운 바이트 [2048]; // 바이트 int int offset = 0에서 읽습니다. int numread = 0; int fsize = (int) 길이; while (오프셋 <fsize && (numread = is.read (bytes, 0, bytes.length))> = 0) {pdata.setdata (bytes, numread); dout.write (pdata.getPackagedAta (), 0, pdata.getPackagedAta () 길이); dout.flush (); 오프셋 += 숫자; float precent = 100.0f * ((float) 오프셋)/((float) fsize); setProgress ((int) precent); } system.out.println ( "Total Send Bytes =" + 오프셋); // 모든 바이트가 if (offset <fsize)에서 읽었는지 확인하십시오. } msocket.shutdownoutput (); // Connection에서 메시지를 성공적으로 전송하는 파일 수신 bufferedInputStream streamReader = new bufferedInputStream (msocket.getInputStream ()); bufferedReader bufferedReader = new bufferedReader (new inputStreamReader (streamReader)); 문자열 donemsg = bufferedReader.Readline (); if ( "done".equals (donemsg)) {parent.showsuccess (); } // 파일 입력 스트림 setProgress (100)를 닫습니다. // dout.close (); msocket.close (); is.close (); System.out.println ( "지금 닫습니다 ..."); 반환 100; }}패킷 클래스는 다음과 같습니다.
패키지 com.gloomyfish.socket.tutorial.filetransfer; / ** * 이것은 TCP 소켓에 대한 매우 간단한 파일 전송 프로토콜 */ public class filedAtapackage {private int datalength; // 패킷의 데이터 길이, 두 바이트 개인 바이트 [] Databuff; // 패킷의 최대 데이터, MEICI의 최대 수는 2048 바이트를 초과하지 않습니다. 공개 최종 정적 바이트 [] eof = new Byte [] { 'e', 'o', 'f'}; public filedatapackage () {datalength = 0; Databuff = 새로운 바이트 [2048]; } public byte [] getPackagedata () {byte [] pdata = new Byte [Datalength]; // END COMMENT SYSTEM.ARRAYCOPY (Databuff, 0, PData, 0, Datalength); 반환 pData; } public void setData (byte [] data, int bsize) {datalength = bsize; for (int i = 0; i <databuff.length; i ++) {if (i <bsize) {databuff [i] = data [i]; } else {databuff [i] = ''; }}}}시간당 전송 된 최대 바이트 수는 2048 바이트입니다. 프로그램의 최종 실행 효과는 다음과 같습니다 (Win7 + JDK6U30) :
위의 내용은이 기사에 관한 모든 것입니다. 모든 사람의 학습에 도움이되기를 바랍니다.