Java的TCP简易socket通信笔记


前言

使用Java实现进程的TCP连接和Socket通信。

一、简单通信

实现Server和Client的简单通信。
需要实现的功能:Client发送“hello server”至服务端,服务端成功接收后发送“hello Client”。然后关闭服务端和客户端。

1. 服务端

首先是Server端的代码

/**
服务端,接收“hello server”语句并发送“hello client”语句
*/
public class SocketTCPSimpleChatServer{
	public static void main(String[] args) throws IOException{
		//1. 在9999端口监听Client
		ServerSocket serverSocket = new ServerSocket(9999);
		//2. 此时socket在阻塞等待,如果有client接入则返回一个Socket对象
		Socket socket = serverSocket.accept();
		//3. 通过IO来读取Client发送过来的消息
		InputStream inputStream = socket.getInputStream();
		byte[] buf = new byte[1024];//使用字节流的方式读取消息内容
		int readLen=0;
		while((readLen=inputStream.read(buf))!=-1){
			System.out,println(new String(buf,0,readLen));
		}
	
		//4. 接收成功后回传“hello client”,这里使用字符流方式(演示两种方式传送)
		BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
		bufferedWriter.writer("hello client");
		bufferedWriter.newLine();//换行符结束,要求对方使用readLine
		bufferedWriter.flush();//需要刷新才能写入通道
		
		//5. 关闭所有流
		outputStream.close();
		inputStream.close();
		socket.close();
		serverSocket.close();
	}
}

2. 客户端

接下来是Client端的代码

/**
客户端,发送“hello server”并接受“hello client”
*/
public class SocketTCPSimpleChatClient{
	public static void main(String[] args) throws Exception{
		//1. 使用InetAddress绑定ip和端口
		Socket socket = new Socket(InetAddress.getLocalHost(),9999);
		//2. 获取输出流并发送hello server
		OutputStream outputStream = new socket.getOutputStream();
		//使用字符流发送
		outputStream.write("hello server".getBytes());
		socket.shutdownOutput();
		
		//3. 使用字符流的方式接收hello client
		InputStream inputStream = socket.getInputStream();
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
		String s = bufferedReader.readLine();//由于server用了newLine
		System.out,println(s);
		
		//4. 关闭相关的流
		inputStream.close();
		outputStream.close();
		socket.close();
	}
}

二、文件上传

思路就是客户端获取文件(这里是图片)的内容存入到二进制数组中,再通过socket传输到服务端,服务端获取成功后保存到相应的文件夹,最后发送ok到客户端表示已经成功接收。

1. 服务端

代码示例如下

public class SocketTCPUploadServer{
	public static void main(String[] args) throws IOException{
		//1. 启动,监听端口
		ServerSocket serverSocket = new ServerSocket(9999);
		Socket socket = serverSocket.accept();
		//2. 接收客户端的信息
		BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
		//另外编写了一个工具类,将流转换成二进制 StreamUtils.java
		byte[] buf = StreamUtils.streamToByteArray(bufferedInputStream);

		//将接收到的内容存到服务器本地
		String serverFilePath = "xxx";
		BufferedOutputStream bufferedOutputStream = new BufferedOuputStream(new FileOutputStream(serverFilePath));
		bufferedOutputStream.write(buf);
		bufferedOutputStream.close();

		//回传接收成功给客户端
		BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		bufferedWriter.write("OK");
		bufferedWriter.newLine();
		bufferedWriter.flush();

		//关闭所有流
		bufferedWriter.close();
		bufferedOutputStream.close();
		bufferedInputStream.close();
		socket.close();
		serverSocket.close();
	}
}

关于InputStream和BufferedInputStream的区别:
BufferedInputStream是一个带有缓冲区域的InputStream,它的继承体系如下:

InputStream
|__FilterInputStream
|__BufferedInputStream

以看作是BufferedInputStream对外提供滑动读取的功能实现,通过预先读入一整段原始输入流数据至缓冲区中,而外界对BufferedInputStream的读取操作实际上是在缓冲区上进行,如果读取的数据超过了缓冲区的范围,那么BufferedInputStream负责重新从原始输入流中载入下一截数据填充缓冲区,然后外界继续通过缓冲区进行数据读取。这样的设计的好处是:避免了大量的磁盘IO,因为原始的InputStream类实现的read是即时读取的,即每一次读取都会是一次磁盘IO操作(哪怕只读取了1个字节的数据),可想而知,如果数据量巨大,这样的磁盘消耗非常可怕。而通过缓冲区的实现,读取可以读取缓冲区中的内容,当读取超过缓冲区的内容后再进行一次磁盘IO,载入一段数据填充缓冲,那么下一次读取一般情况下就直接可以从缓冲区读取,减少了磁盘IO。
————————————————
原文链接:https://blog.csdn.net/niyingxunzong/article/details/33335485

2. 客户端

客户端代码如下:

public class SocketTCPUploadClient{
	public static void main(String[] args) throws Exception{
		Socket socket = new Socket(InetAddress.getLocalHost(),9999);
		//获取所要上传的文件内容
		String filePath = "xxx";
		BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileOutputStream(filePath));
		byte[] buf=StreamUtils.streamToByteArray(bufferedInputStream);
		
		//创建一个输出流传输内容
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
		bufferedOutputStream.write(buf);
		bufferedOutputStream.close();
		socket.shutdownOutput();

		//接收服务端的响应
		InputStream inputStream = socket.getInputStream();
		String s = StreamUtils.streamToString(inputStream);
		System.out.println(s);

		//关闭所有流
		inputStream.close();
		bufferedInputStream.close();
		socket.close();
	}
}

3. 工具类的实现

上面代码中所用到的工具类StreamUtils.java代码如下:

/**
StreamUtils.java
实现了两个方法,分别是streamToByteArray()和streamToString()
*/

public class StreamUtils{
	public static byte[] streamToByteArray(InputStream is) throws Exception{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		byte[] b = new byte[1024];
		int readLen = 0;
		while((readLen=is.read(b))!=-1){
			bos.write(b,0,readLen);
		}
		//将流转换成二进制数组
		byte[] array = bos.toByteArray();
		bos.close();
		return array;
	}
	
	public static String streamToString(InputStream is) throws Exception{
		BufferedReader bufferdReader = new BufferedReader(new InputStreamReader(is));
		StringBuilder builder = new StringBuilder();
		String line;
		while((line=builder.readLine())!=null){
			builder.append(line+"\r\n");
		}
		return builder.toString();
	}
}

总结

文章给出了简易的TCP进程通信代码以及客户端上传文件至服务端的简单代码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值