首页 > 技术文章 > 使用TCP实现图片上传

GoodBless 2019-06-18 16:25 原文

  上一篇写到使用UDP实现文字交互,UDP和TCP各有千秋,所以现在写一个TCP上传图片的demo。

  TCP通信同UDP通信区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据。TCP通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。

  在开发TCP程序时,首先需要创建服务器端程序,JDKjava.net包中提供了一个ServerSocket类。

 

  使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上(参数port就是端口号)。

 

  ServerSocket对象负责监听某台计算机的某个端口号,在创建ServerSocket对象后,需要继续调用该对象的accept()方法,接收来自客户端的请求。当执行了accept()方法之后,服务器端程序会发生阻塞,直到客户端发出连接请求,accept()方法才会返回一个Scoket对象用于和客户端实现通信,程序才能继续向下执行。

  ServerSocket对象可以实现服务端程序,但只实现服务器端程序还不能完成通信,此时还需要一个客户端程序与之交互,为此JDK提供了一个Socket类,用于实现TCP客户端程序。

 

参数address用于接收一个InetAddress类型的对象,该对象用于封装一个IP地址。

 

Socket的常用方法,如图所示。

 

Socket类的常用方法中,getInputStream()getOutStream()方法分别用于获取输入流和输出流。当客户端和服务端建立连接后,数据是以IO流的形式进行交互的,从而实现通信。

 

下面上代码

客户端

 

// 创建Socket对象,连接服务器Socket socket = new Socket("127.0.0.1",8000);
这段代码只要写TCP客户端必定出现

/*
* 实现TCP客户端,连接到服务器
* 和服务器实现数据交换
* 实现TCP客户端程序的类java.net.Socket
*
* 构造方法:
* Socket(String host,int port) 传递服务器IP和端口号
* 注意:构造方法只要运行,就会和服务器进行连接,连接失败,抛出异常
* OutputStream getOutputStream() 返回套接字的输出流
* 作用:将数据输出,输出到服务器
* InputStream getInputStream() 返回套接字的输入流
* 作用:从服务器端读取数据
* 客户端服务器数据交换,必须使用套接字对象Socket中的获取IO流,自己new流,不行
*/

 

package com.lty.wangluotcpPhotoUp;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
 * 实现TCP图片上传客户端
 * 实现步骤
 * 1.Socket套接字连接服务器
 * 2.通过Socket获取字节输出流,写图片
 * 3.使用自己的流对象,读取图片数据源
 * 		FileInputStream
 * 4.读取图片使用字节输出流,将图片写到服务器
 * 	采用字节数组进行缓冲
 * 5.通过Socket套接字获取字节输入流
 * 	读取服务器发回来的上传成功
 * 6.关闭资源
 */
public class TCPClient {

	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1",8000);
		//获取字节输出流,图片写到服务器
		OutputStream out = socket.getOutputStream();
		// 创建字节输入流,读取本机上的数据源图片
		FileInputStream fis = new FileInputStream("c:\\t.jpg");
		//开始读写字节数组
		int len = 0;
		byte[] bytes =new byte[1024];
		while((len = fis.read(bytes))!=-1) {
			out.write(bytes,0,len);
		}
		//给服务器写终止序列
		socket.shutdownOutput();
		
		//获取字节输入流,读取服务器的上传成功
		InputStream in = socket.getInputStream();
		len = in.read(bytes);
		System.out.println(new String(bytes,0,len));
		
		fis.close();
		socket.close();
	}

}

 

服务器:

这个demo是多线程的,所以有如下代码

package com.lty.wangluotcpPhotoUp;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.util.Random;

public class Upload implements Runnable{

	private Socket socket;
	
	public Upload(Socket socket) {this.socket=socket;}
	
	public void run() {
		//通过客户端连接对象,获取字节输入流,获取客户端图片

		try {
			InputStream in = socket.getInputStream();
			//将目的文件夹封装到File对象
			File upload = new File("d:\\upload");
			if(!upload.exists())
				upload.mkdirs();
			
			//防止文件同名被覆盖,重新定义文件名字
			//规则: 	域名+毫秒值+6位随机数
			String filename="itcast"+System.currentTimeMillis()+new Random().nextInt(999999)+".jpg";
			//创建字节输出流,将图片写入到目的文件夹中
			FileOutputStream fos = new FileOutputStream(upload+File.separator+filename);
			//读写字节数组
			byte[] bytes=new byte[1024];
			int len=0;
			while ((len=in.read(bytes))!=-1) {
				fos.write(bytes,0,len);
			}
			//通过客户端连接对象获取字节输出流
			//上次成功写回到客户端
			socket.getOutputStream().write("上传成功".getBytes());
			
			fos.close();
			socket.close();
		} catch (Exception ex) {
		}
	}
}

写服务器端下面两端代码是肯定会出现

ServerSocket server = new ServerSocket(8000);

//调用服务器套接字对象中的方法accept()获取套接字对象

Socket socket =server.accept();

/*
* 实现TCP服务程序
* 表示服务器程序的类java.net.ServerSocket
* 构造方法:
* SreverSoceket(int port)传递端口号
*
* 很重要的事情:必须要获得客户端的套接字对象Socket
* Socket accept()
* 服务器可以获取到客户端的套接字对象Socket
*
*/

package com.lty.wangluotcpPhotoUp;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPThreadServer {
	public static void main(String[] args)throws IOException {
		ServerSocket server = new ServerSocket(8000);
		while(true) {
		//获取一个客户端,必须开启新线程
		Socket socket=server.accept();
		new Thread(new Upload(socket)).start();
		}
	}
}

  效果图

网络编程与IO密不可分,但是IO内容太过繁杂,这里就不一一说了

这里涉及到了多线程请见下回分解

 

 

 

 

 

推荐阅读