900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【Java】TCP Socket编程案例——文件传输聊天工具

【Java】TCP Socket编程案例——文件传输聊天工具

时间:2018-08-31 12:20:28

相关推荐

【Java】TCP Socket编程案例——文件传输聊天工具

TCP(传输控制协议)是面向连接的可靠数据传输协议。TCP连接一旦建立起来,一直占用,直到关闭连接。另外,TCP为了保证数据的正确性,会重发一切没有收到的数据,还会对数据内容进行验证,并保证数据传输的正确顺序。因此TCP协议对系统资源的要求较多。

案例一:文件上传工具

上传过程是一个单向的socket通信过程。

客户端通过文件输入流读取文件,然后从Socket获得输入流写入数据,写入数据完成上传成功,客户端任务完成。

服务端从Socket获得输入流,然后写入文件输出流,写入数据完成上传成功,服务端任务完成。

服务器端UploadServer代码如下:

package wangluobiancheng;import java.io.BufferedInputStream;import java.io.FileOutputStream;import java.io.IOException;import .ServerSocket;import .Socket;public class UploadServer {public static void main(String[] args) {System.out.println("服务端运行...");try {//创建一个ServerSocket监听8080端口的客户请求ServerSocket server=new ServerSocket(8080);//使用accept()阻塞当前线程,等待客户端请求Socket socket=server.accept();BufferedInputStream in=new BufferedInputStream(socket.getInputStream());//由文件输出流创建缓冲输出流FileOutputStream out=new FileOutputStream("TestDir/subDir/coco.jpg");//准备一个缓冲区byte[] buffer=new byte[1024];//首次从Socket读取数据int len=in.read(buffer);while(len!=-1){//写入数据到文件out.write(buffer,0,len);//再次从Socket读取数据len=in.read(buffer);}System.out.println("接收完成!");} catch (IOException e) {e.printStackTrace();}}}

(注意:由于当前线程是主线程,所以server.accept()会阻塞主线程,阻塞主线程是不明智的,如果是在一个图形界面的应用程序,阻塞主线程会导致无法进行任何的界面操作,就是常见的“卡”现象,所以最好是把server.accept()语句放到子线程中。)

客户端UploadClient代码如下:

package wangluobiancheng;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.IOException;import .Socket;import .UnknownHostException;public class UploadClient {public static void main(String[] args) {System.out.println("客户端运行...");//向本机的8080端口发出请求Socket socket;try {socket = new Socket("127.0.0.1",8080);//由Socket获得输出流,并创建缓冲输出流BufferedOutputStream out=new BufferedOutputStream(socket.getOutputStream());//创建文件输入流FileInputStream fin=new FileInputStream("TestDir/coco.jpg");//由文件输入流创建缓冲输入流BufferedInputStream in=new BufferedInputStream(fin);//准备一个缓冲区byte[] buffer=new byte[1024];//首次读取文件int len=in.read(buffer);while(len!=-1){//数据写入Socketout.write(buffer,0,len);//再次读取文件len=in.read(buffer);}System.out.println("上传成功!");} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}

测试案例时,先运行服务器,再运行客户端。

注意当前运行的路径是工程根目录,需要将用到的文件夹创建在根目录下。本案例文件结构如下所示:

测试Socket程序要查看多个控制台信息,可以在Eclipse控制台上面的工具栏中单击“选择控制台”按钮实现切换。

案例二:聊天工具

案例一介绍的只是单向传输的Socket,Socket可以双向数据传输,比较有代表性的案例就是聊天工具。

首先客户端通过键盘输入字符串,通过标准输入流读取字符串,然后通过Socket获得输入流,将字符串写入输入流。

接着服务器通过Socket获得输入流,从输入流中读取来自客户端发送过来的字符串,然后通过标准输入流输出到显示器的控制台。服务器向客户端传送字符串过程类似。

服务器端ChatServer代码入下:

package wangluobiancheng;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import .ServerSocket;import .Socket;public class ChatServer {public static void main(String[] args) {System.out.println("服务器运行...");Thread t=new Thread(()->{try ( //使用自动资源管理//创建一个ServerSocket监听端口8080客户请求ServerSocket server=new ServerSocket(8080);//使用accept()阻塞等待客户端请求Socket socket=server.accept();//从socket中获得数据输入流DataInputStream in=new DataInputStream(socket.getInputStream());//从socket中获得数据输出流DataOutputStream out=new DataOutputStream(socket.getOutputStream());//System.in是标准输入流,使用标准输入流创建缓冲输入流BufferedReader keyboardIn=new BufferedReader(new InputStreamReader(System.in))){while(true){/*接收数据*///数据输入流读取UTF编码的字符串String str=in.readUTF();//打印接收的数据System.out.printf("从客户端接收的数据:【%s】\n",str);/*发送数据*///读取键盘输入的字符串String keyboardInputString=keyboardIn.readLine();//结束聊天if(keyboardInputString.equals("bye")){break;}//发送out.writeUTF(keyboardInputString);out.flush();}} catch (IOException e) {e.printStackTrace();}});t.start();}}

上述代码创建一个子线程,将网络通信放到子线程中处理是一种很好的做法,因为网络通信往往有线程阻塞过程,放到子线程中处理就不会阻塞主线程了。

自动资源管理:一般try-catch语句后面还跟有一个finally代码块,无论try正常结束还是catch异常结束都会执行finally代码块,可以在finally语句中释放资源。而使用finally代码块释放资源会导致程序代码大量增加,在Java 7之后提供的自动资源管理技术可以代替finally代码块,不需要自己关闭这些资源,释放过程交给了JVM。自动资源管理是在try语句上的扩展,在try语句后面添加一对小括号"()",其中是声明或初始化资源语句,可以有多条语句,语句之间用分号";"分隔。

注意:所有可以自动管理的资源需要实现AutoCloseable接口,具体哪些资源实现AutoCloseable接口需要查询API文档。

客户端ChatClient代码如下:

package wangluobiancheng;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import .Socket;import .UnknownHostException;public class ChatClient {public static void main(String[] args) {System.out.println("客户端运行...");Thread t=new Thread(()->{try (//向127.0.0.1主机8080端口发出连接请求Socket socket=new Socket("127.0.0.1",8080);DataInputStream in=new DataInputStream(socket.getInputStream());DataOutputStream out=new DataOutputStream(socket.getOutputStream());BufferedReader keyboardIn=new BufferedReader(new InputStreamReader(System.in))){while(true){/*发送数据*///读取键盘输入的字符串String keyboardInpuStream=keyboardIn.readLine();//结束聊天if(keyboardInpuStream.equals("bye")){break;}//发送out.writeUTF(keyboardInpuStream);out.flush();/*接收数据*/String str=in.readUTF();//打印接收的数据System.out.printf("从服务器接收的数据:【%s】\n",str);}} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}System.out.println("客户端停止!");});t.start();}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。