Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2244278
  • 博文数量: 556
  • 博客积分: 11457
  • 博客等级: 上将
  • 技术积分: 5973
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-24 22:33
文章分类

全部博文(556)

文章存档

2013年(22)

2012年(74)

2011年(460)

分类: Java

2012-06-26 00:23:37

首先实现简单的服务器端代码如下:

点击(此处)折叠或打开

  1. package cn.xaut.ftp;

  2. import java.io.DataInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.net.ServerSocket;
  8. import java.net.Socket;

  9. public class ChatServer {
  10.     
  11.     public static void main(String[] args) {
  12.         ChatServer cs =new ChatServer();
  13.         cs.setUpServer(9090);
  14.     }

  15.     private void setUpServer(int port) {
  16.        try {
  17.         ServerSocket server =new ServerSocket(port);
  18.         System.out.println("服务器创建成功!"+port);
  19.         
  20.         while(true){
  21.              Socket client =server.accept();
  22.              System.out.println("Incoming client:"+client.getRemoteSocketAddress());
  23.              //调用处理连接对象的方法去处理连接
  24.              processChat(client);
  25.         }
  26.     } catch (IOException e) {
  27.         e.printStackTrace();
  28.     }        
  29.     }
  30.      //处理客户端进入的连接对象
  31.     private void processChat(Socket client) {
  32.          try {
  33.             OutputStream out =client.getOutputStream();
  34.             InputStream ins=client.getInputStream();
  35.             //将输入流包装为DataInputStream方便读取原始类型的流
  36.             DataInputStream dins=new DataInputStream(ins);
  37.             while(true){
  38.                 //开始读取数据,没一条消息,总是以一个int开头
  39.                 //1.读消息长度,readInt()方法底层从流中读取4个字节,组成一个int
  40.                 int totalLen=dins.readInt();
  41.                 System.out.println("*********进入一条消息总长:"+totalLen);
  42.                 //2.读取消息类型标识,只读取一个字节
  43.                 byte flag =dins.readByte();
  44.                 System.out.println("消息接收类型为:"+flag);
  45.                 //3.读取目标客户号码,一个int
  46.                 int destNum =dins.readInt(); //消息头解析完毕
  47.                 System.out.println("消息接收目标用户号是:"+destNum);
  48.                 
  49.                 //根据消息的类型,读取消息体部分
  50.                 if(flag==1){
  51.                     byte[] data=new byte[totalLen-4-1-4];
  52.                     //从流中读取data.length个字节放入数组中
  53.                     dins.readFully(data);
  54.                     String msg=new String(data); //转成字符串
  55.                     System.out.println("发送文本给"+destNum+" 内容是:"+msg);
  56.                 }else if(flag==2){ //文件数据包体解析
  57.                     System.out.println("发送文件给:"+destNum);
  58.                     byte[] data=new byte[256];
  59.                     dins.readFully(data); //读取256个字节做文件名字
  60.                     //解析出了文件名字,并去除末尾空格
  61.                     String fileName =new String(data).trim();
  62.                     System.out.println("读到的文件名字是:"+fileName);
  63.                     //余下的字节就是文件内容
  64.                     data =new byte[totalLen-4-1-4-256]; //文件字节数据总长
  65.                     dins.readFully(data); //读入文件的字节
  66.                     //保存文件到当前目录下
  67.                     FileOutputStream fous=new FileOutputStream(fileName);
  68.                     fous.write(data);
  69.                     fous.flush();
  70.                     fous.close();
  71.                     System.out.println("文件保存完成!");
  72.                 }else{
  73.                     System.out.println("收到未知数据包!"+flag);
  74.                     client.close();
  75.                 }
  76.             }
  77.         } catch (IOException e) {
  78.             e.printStackTrace();
  79.         }
  80.          
  81.     }

  82. }
简单的客户端代码如下:

点击(此处)折叠或打开

  1. package cn.xaut.ftp;
  2. import java.io.*;
  3. import java.net.Socket;
  4. import java.net.UnknownHostException;
  5. import java.util.Scanner;
  6. public class ChatClient {

  7.      private DataOutputStream dous; //输出流对象
  8.      /**
  9.      * 向流中写入定长字节,如果不足,补二进制0
  10.      * @param out:要写入的流
  11.      * @param str:字符串
  12.      * @param len:要写入的长度
  13.      */
  14.     public static void main(String[] args) {
  15.          ChatClient qqc=new ChatClient();
  16.          qqc.conn2Server("localhost", 9090);
  17.     }
  18.     
  19.     private void writeString(DataOutputStream out,String str,int len){
  20.         byte[] data=str.getBytes();
  21.         try {
  22.             out.write(data);
  23.             //假设都是短,需要补0
  24.             while(len>data.length){
  25.                 out.writeByte('\0'); //补二进制0
  26.                 len--;
  27.             }
  28.         } catch (IOException e) {
  29.             e.printStackTrace();
  30.         }
  31.     }
  32.     
  33.     /**
  34.      * 发送一条文本消息
  35.      * @param msg:消息内容
  36.      * @param destNum:接收者号码
  37.      * 打包的过程
  38.      */
  39.      private void sendTextMsg(String msg,int destNum){
  40.          try {
  41.              byte[] strb=msg.getBytes(); //得到消息的字节数
  42.              int totalLen=4+1+4+strb.length;
  43.              System.out.println("发送总 长度为:"+totalLen);
  44.              dous.writeInt(totalLen); //总长
  45.              dous.writeByte(1); //类型:1为文本消息
  46.              dous.writeInt(destNum); //写入目标用户号
  47.              dous.write(strb); //写入消息内容
  48.              dous.flush();
  49.             
  50.         } catch (IOException e) {
  51.             e.printStackTrace();
  52.         }
  53.      }
  54.     
  55.      /**
  56.      * 发送一个文件数据包
  57.      * @param fileName:文件绝对路径名
  58.      * @param destNum: 目标用户号码
  59.      */
  60.      private void sendFileMsg(String fileName,int destNum){
  61.          try {
  62.              //根据文件名创建文件对象
  63.              File file =new File(fileName);
  64.              //根据文件对象,构造一个输入流
  65.             InputStream ins=new FileInputStream(file);
  66.             int fileDataLen =ins.available(); //文件数据总长
  67.             int totalLen =4+1+4+256+fileDataLen; //得到了要发送数据包的总长
  68.             dous.writeInt(totalLen);
  69.             dous.writeByte(2); //类型:2,即文件数据包
  70.             //写入目标用户号
  71.             dous.writeInt(destNum);
  72.             //文件名:得到文件的短名字
  73.             String shortFileName =file.getName();
  74.             //写入文件名,不足256个长度时,补\0
  75.             writeString(dous,shortFileName,256);
  76.             byte[] fileData =new byte[fileDataLen];
  77.             ins.read(fileData); //读入文件数据
  78.             dous.write(fileData); //写出到服务器的流中
  79.             dous.flush(); //刷新流
  80.             
  81.          }catch (FileNotFoundException e) {
  82.             e.printStackTrace();
  83.         } catch (IOException e) {
  84.             e.printStackTrace();
  85.         }
  86.      }
  87.     
  88.      public void conn2Server(String ip,int port){
  89.          //创建一个到服务器端的Socket对象
  90.          try {
  91.             Socket client =new Socket(ip,port);
  92.             //得到输入输出流对象
  93.             InputStream ins =client.getInputStream();
  94.             OutputStream out=client.getOutputStream();
  95.             //将输出流包装为DataOutputStream对象
  96.             dous=new DataOutputStream(out);
  97.             
  98.             int testCount=0;
  99.             while(true){
  100.                 System.out.println("登录服务器成功,请选择你要发送的类型(1:聊天 2:文件)");
  101.                 //让用户从命令行输入要发送的文件名字
  102.                 Scanner sc=new Scanner(System.in);
  103.                 int type=sc.nextInt();
  104.                 
  105.                 if(type==1){ //发文本
  106.                     sendTextMsg("abc聊天内容"+testCount,8888);
  107.                 }
  108.                 if(type==2){ //发文件,注这个文件必须存在
  109.                     sendFileMsg("e://1.jpg",8888);
  110.                 }
  111.                 testCount++;
  112.             }
  113.         } catch (UnknownHostException e) {
  114.             e.printStackTrace();
  115.         } catch (IOException e) {
  116.             e.printStackTrace();
  117.         }
  118.      }

  119. }
以上示例了简单的协议制定、实现思路及方法。我们将消息数据按协议规则写入到流中的过程称之为“打包”过程,从流中读取的过程称之为“解包”过程。
在线JavaDoc:(中文版)


附件:
 FTP.zip  
经典文件传输:
 文件传输系统.rar  
阅读(1259) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~