Java中利用Socket传输信息或文件

Socket的客户端与服务端传输数据与文件


本文中的是使用TCP协议进行文件传输

Socket

套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

信息与文件传输使用C/S(Client/Server)。

步骤

1、启动服务端,等待客户端连接。
2、启动客户端连接服务端。
3、传输数据。
4、关闭客户端。
5、关闭服务端。

代码

首先启动服务端

package priv.zb.socket;

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

public class FileServer {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		ServerSocket server = null;
		Socket socket = null;
		//向外界暴露一个端口9999的服务,默认IP为本机IP:127.0.0.1
		server = new ServerSocket(9999);
		//返回一个Socket对象
		socket = server.accept();
		/**
		 *
		 * 启动服务端之后,会在 server.accept(); 方法处等待客户端的
		 * 连接,当启动客户端连接上服务端之后走过此方法运行后面的代码。
		 */
		System.out.println("接收到客户端的连接");
		//服务端向客户端发送消息	通过OutputStream
		//发出信息使用输出流OutputStream,接收信息使用输入咯InputStream
		OutputStream output = socket.getOutputStream();
		
		//传输字符串
//		byte[] bs = new byte[100];
//		output.write("Hello".getBytes());
		
		//传输文件
		String filePath = "存放文件路径";
		File file = new File(filePath );
		byte[] fileBytes = new byte[100];		//定义文件每次发送大小
		//读入到内存中,new 一个inputStream即可
		//文件较大,不能一次性发送完毕,因此需要循环操作
		InputStream fileIn = new FileInputStream(file);
		int len = -1;
		while((len = fileIn.read(fileBytes)) != -1) {
			output.write(fileBytes, 0, len);
		}
		//接受客户端消息
//		InputStream in = socket.getInputStream();
//		in.read(bs);
//		System.out.println("Server接收到信息:" + new String(bs));
		System.out.println("发送成功");
		output.close();
		fileIn.close();
	}
}

之后启动客户端

package priv.zb.socket;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class FileClient {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws UnknownHostException, IOException {
		//建立连接
		//客户端访问服务端发布的服务
		Socket socket = new Socket("192.168.0.108",9999);
		//通过InputStream接收信息
		InputStream input = socket.getInputStream();
		byte[] fileBytes = new byte[100];
		File file = new File("E:\\JAVA\\Java SE\\srcCopy.zip");
		OutputStream output = new FileOutputStream(file);
		int len = -1;
		while( (len = input.read(fileBytes)) != -1) {
			output.write(fileBytes, 0, len);
		}
		
		//客户端接收到信息返回一个标识
//		byte[] bs = new byte[100];
//		input.read(bs);
//		System.out.println("Client 接收到消息:" + new String(bs));
		
		//客户端向服务端发送一个消息
//		OutputStream output = socket.getOutputStream();
//		output.write("World".getBytes());
		System.out.println("接收成功!!");
		output.close();
		input.close();
	}
}

这个代码在客户端连接一次之后,服务端便会主动关闭。但是在实际的使用中一般不会只使用一次服务端,将会不断地重复连接服务端这一过程。因此使用while(true)死循环来保持服务端的始终开启,利用多线程来解决这一问题。

优化

使用多线程是在服务端

服务端

package priv.zb.socket.runable;

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

public class FileServer {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		//向外界暴露一个端口9999的服务,默认IP为本机IP:127.0.0.1
		ServerSocket server = new ServerSocket(9999);
		while(true) {
			Socket socket = server.accept();
			//使用构造方法传入一个Socket对象与下载线程保持关联
			new Thread(new MyDownload(socket)).start();
			//下载线程
			/*
			 * MyDownload download = new MyDownload(socket);
			 * //Runnable变为Thered对象 
			 * new Thread(download).start();
			 */
		}
	}
}

下载线程:MyDownload.java

package priv.zb.socket.runable;

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

public class MyDownload implements Runnable {

	//Mydownload.java与Server之间使用Socket对象联系
	private Socket socket;
	public MyDownload(Socket socket) {
		this.socket = socket;
	}
	@Override
	public void run() {
		//返回一个Socket对象
		OutputStream output =null;
		InputStream fileIn = null;
		try {
			System.out.println("接收到客户端的连接");
			//服务端向客户端发送消息	通过OutputStream
			File file = new File("E:\\JAVA\\Java SE\\src.zip");
			byte[] fileBytes = new byte[100];		//定义文件每次发送大小
			//读入到内存中,new 一个inputStream即可
			//文件较大,不能一次性发送完毕,因此需要循环操作
			fileIn = new FileInputStream(file);
			int len = -1;
			output = socket.getOutputStream();
			while((len = fileIn.read(fileBytes)) != -1) {
				output.write(fileBytes, 0, len);
			}
			System.out.println("发送成功");
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			try {
				if(output != null) output.close();
				if(fileIn != null) fileIn.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

之后即可多次传输信息不关闭服务端。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值