Java基础21-TCP

一.TCP传输数据
 1.TCP和UDP的区别
  UDP是无连接的, 指定地址和端口后就可以发送, 数据不安全, 速度快.
  TCP是面向连接的, 区分客户端和服务端, 数据安全.


 2.上传文件
 服务端:
  0.创建upload文件夹
  1.创建ServerSocket, 在循环中等待和客户端请求, 每收到一个请求, 开启一条新线程.
  5.获取输入输出流
  7.接收文件名, 接收文件大小, 判断upload文件夹中该文件是否存在
  8.如果存在, 发送提示消息到客户端, 服务端return
  9.如果不存在, 发送提示消息到客户端
  13.接收客户端传输数据, 从Socket中读取数据, 写出到文件中
  
 客户端:
  2.创建BufferedReader, 从键盘接收一个文件路径, 验证是否合法
  3.创建Socket, 连接服务端
  4.获取输入输出流
  6.将文件名发送到服务端, 将文件大小发送到服务端
  10.接收提示消息, 判断是否存在
  11.如果存在, 在客户端打印提示, return
  12.如果不存在, 开始上传, 从文件中读取, 写出到Socket中

 
二.telnet使用
 1.设置回显
  telnet - 回车
  set localecho - 回车
  quit - 回车
 2.使用
  telnet 地址 端口 - 回车
  ctrl + ] - 回车
  输入数据
注意:
  telnet是逐个字符发送的, 输入一个字符就发送一个字符

 

三.多线程文件上传及断点续传

源代码:

   客户端Client

package cn.base24.tcp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

/*
 * 版本v2.0:(add:断点续传)
 * 	使用TCP传输文件的客户端:
 */
public class FileUploadClient2 {

	public static void main(String[] args) {
		FileInputStream fi = null;
		Socket socket = null;
		try {
			socket = new Socket("192.168.1.106", 6789);
			
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedReader brReadKey = new BufferedReader(new InputStreamReader(System.in));
			PrintStream ps = new PrintStream(socket.getOutputStream());
			
			File file = getFile(brReadKey);		//验证输入的路径
			
			ps.println(file.getName());			//传输文件名和文件大小,以确定是否需要断点续传
			ps.println(file.length());
			
			String line = br.readLine();		//接收服务端返回的数据
			long lengthDest = 0;
			long skipNum = 0;					//记录需要跳过的字节数
			
			if("文件已存在.请不要重复上传!".equals(line)) {		//若文件完整且重复,返回是-文件已存在.请不要重复上传!
				System.out.println("文件已存在.请不要重复上传!");
				return;
			} else {
				lengthDest = Integer.parseInt(line);		//将返回的数据,转换
				if(lengthDest != file.length()) {			//比较大小是否一样,不一样则将服务器端的大小作为需要跳过的字节数
					skipNum = lengthDest;					//若是0,则表示服务器端没有该文件,则跳过的数目就是0
				}
			}
			
			System.out.println( skipNum ==0 ? "开始上传..." : "断点续传...");		
			fi = new FileInputStream(file.toString());		
			OutputStream out = socket.getOutputStream();	
			int len = 0;
			byte[] b = new byte[1024];						
			
			fi.skip(skipNum);								//跳过字节数
			while((len= fi.read(b))!=-1) {
				out.write(b, 0, len);
			}			
			System.out.println(skipNum ==0 ? "上传成功!" : "断点续传结束!");		
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(fi != null)
					fi.close();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if(socket != null)
						socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/*
	 * 从键盘接收源文件的路径,保证输入的文件路径正确
	 */
	private static File getFile(BufferedReader brReadKey) throws IOException {		
		String line =null;
		File file = null;
		System.out.println("请输入需要上传的文件路径:");
		while(true) {
			
			line = brReadKey.readLine();
			file = new File(line);
			if(!file.exists()) {
				System.out.println("文件不存在!请输入需要上传的文件路径:");
			} else if(file.isDirectory()) {
				System.out.println("暂不支持上传文件夹功能!请输入需要上传的文件路径:");
			} else{
				break;
			}
		}
		return file;
	}
	
}

 

服务端Server:

package cn.base24.tcp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 版本v2.0:(add:断点续传) ---<注意: 若是断点续传,则应该是追加数据!!!!!!!!!!!>
 * 	使用TCP传输文件的服务端:
 */
public class FileUploadServer2 {

	public static void main(String[] args) {
		ServerSocket serverSocket = null;
		
		final File dir = new File("upload");
		dir.mkdir();
		
		try {
			serverSocket = new ServerSocket(6789);
			
			while(true) {
				
				final Socket socket = serverSocket.accept();		
				
				new Thread() {										
					public void run() {
						FileOutputStream out = null;
						try {
							BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
							PrintStream ps = new PrintStream(socket.getOutputStream());
							
							String fileName = br.readLine();		//接收数据为: 文件名和文件大小;
																	//返回数据为文件的大小,若存在返回实际大小,不存在则返回0
							long lengthSrc = Long.parseLong(br.readLine());
							boolean flag = false;					//标记是否是续传文件,true为续传,false为正常传输
							
							File file = new File(dir, fileName);	//Modify: 如文件已存在,再检查文件大小是否一致					
							if( file.exists() ) {					//若大小不一致,返回文件大小,以便客户端直接跳过已传输部分	
								if(file.length()==lengthSrc) {
									ps.println("文件已存在.请不要重复上传!");
									return;
								}
								else {
									ps.println( file.length() );
									flag = true;
								}
							} else {
								ps.println(0);								
							}
										
							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");	
							String time = sdf.format(new Date());
							String ip = socket.getInetAddress().getHostAddress();
							long start = System.currentTimeMillis();
							System.out.println(ip +"上传: <"+file.getName() + ">文件, 在" + time + ( flag ? " 断点续传..." : " 开始上传..."));
							
							
							InputStream in = socket.getInputStream();
							if(flag) {
								out = new FileOutputStream(file, true);		//注意: 若是断点续传,则应该是追加数据!!!!!!!!!!!
							} else {
								out = new FileOutputStream(file);	
							}
										
							int len = 0;
							byte[] b = new byte[1024];
							while((len= in.read(b))!=-1) {			
								out.write(b, 0, len);
							}
							
							time = sdf.format(new Date());			
							long end = System.currentTimeMillis();
							System.out.println(ip +"上传: <" + file.getName() + ">文件, 在" + time + ( flag ? " 续传完成, 耗时: " : " 上传完成, 耗时: ") + (end -start) +"毫秒");
							
						} catch (IOException e) {
							e.printStackTrace(); 
						} finally {
							try {
								if(out != null) {
									out.close();
								}
							} catch (IOException e) {
								e.printStackTrace();
							} finally {
								try {
									if(socket != null) {
										socket.close();
									}
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}
				}.start();

			}	
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(serverSocket != null)
					serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		
	}
		
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值