Java IO之Socket通信

来源:互联网 发布:iptv管理系统源码下载 编辑:程序博客网 时间:2024/06/06 12:46

一、通讯协议TCP、UDP

Java Socket通信是基于TCP协议来完成的。讲Socket通信之前有必要先了解这两种底层协议。

  • TCP协议是面向连接、保证高可靠性(数据无丢失、数据无失序、数据无错误、数据无重复到达)传输层协议。TCP协议通过三次握手建立连接,四次握手断开连接,带重传功能的肯定确认来保证可靠传输。其中HTTP协议就是基于TCP协议来实现的。HTTP1.0默认短连接,HTTP1.1默认使用长连接,通过Keep-Alive来控制长连接时间,在同一个TCP连接中,只有上一个请求得到响应之后下一个请求才会发送。

  • UDP协议是无连接,不保证可靠的传输层协议。传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。

二、字符流和字节流

java在对文件、图片、视频等资源的操作上提供了字符流和字节流的操作方式,但是由于计算机中使用的是二进制来存储文件,而字符流对文件操作时会经历编码和解码阶段,所以字节流的操作要比字符流的操作效率高。但是字符流有很多操作都方便编程人员,对于文件的读取展现,我们可以使用字符流,免去了我们程序对字节和字符的转换。除此之外,字符流与字节流还有一个根本的区别。字节流不需要用到缓冲区,而字符流会先将数据放到缓存区再写入文件。如下例子,我们为了研究字符流和字节流是否用到缓冲区,不关闭输出流,因为在关闭输出流之前,会将缓冲区的内容全部输出,类似于调用flush()。

字节流:

package ioTest;import java.io.FileOutputStream;public class ByteTest {    public static void main(String[] arg) {        try {            FileOutputStream fileOutputStream = new FileOutputStream("e:/ds2.txt");            fileOutputStream.write("hello world".getBytes());            //fileOutputStream.close();        } catch (Exception e) {            e.printStackTrace();        }    }}

结果:文件ds2.txt显示【hello world】。

字符流:

package ioTest;import java.io.FileWriter;import java.io.IOException;public class CharTest {    public static void main(String[] arg){        try {            FileWriter fileWriter = new FileWriter("e:/ds.txt");            fileWriter.write("hello world");            //fileWriter.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

结果:文件ds.txt文件内容为空。

二进制I/O中常用的流操作类
InputStream:FileInputStream、FilterInputStream、ObjectInputStream。
FilterInputStream:DateInputStream、BufferedInputStream。

  • FileInputStream以文件、文件名为构造函数创建输入流,是大部分输入流的起始点,其他输入流通过包装该输入流来进行操作。
  • DateInputStream通过包装FileInputStream或其他字节输入流来构造,提供了多种数据读取方式,readByte()、readChar()、readInt()、readLine()、readUTF()等等。
  • BufferedInputStream在读取文件时创建缓冲区,默认是512字节。
    ObjectInputStream包含所有DateInputStream的功能,另外还增加了对对象的操作。

文本I/O中常见的流操作
BufferedReader、InputStreamReader、FileReader

  • FileReader大部分字符流读取文件的起点。
  • InputStreamReader连通字符流与字节流的枢纽,可以通过字节流来构造该字符流,然后通过其他字符流再包装该字符流,并且设置编码方式。如:
new BufferedReader(new InputStreamReader(new   FileInputStream(fileName),"UTF-8")); 
  • BufferedReader在读取文件时创建缓冲区。

三、通信实现

前面介绍了相关的基础知识之后就直接上代码吧,另外对于多线程不太熟悉的朋友自己去补习一下。本程序包含三个类,具体的运行步骤在代码中做了详细的解释:

  • SocketClient:socket通信客户端,运行时可以多次启动来模拟多个客户端。
  • SocketServer:socket通信服务端,这里只有一个服务端,对于不同的客户端请求创建不同的线程来进行处理,通过线程池来进行管理。
  • SocketThread:socket通信基础线程,供服务端调用,用于与客户端进行交互。
package socketTest;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.util.Scanner;public class SocketClient {    private DataOutputStream out;//通信输出流    private DataInputStream in;//通信输入流    private Socket socket;    public static void main(String[] arg){        try {            SocketClient socketClient = new SocketClient();            socketClient.initParam("127.0.0.1",6644);            System.out.println("请输入向服务器发送的内容:");            socketClient.send();        } catch (Exception e) {            e.printStackTrace();        }    }    //初始化参数    public void initParam(String ipAddress, int port) throws Exception{        this.socket = new Socket(ipAddress, port);        this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));        this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));    }    //发送内容    public void send() throws IOException{        while(true){            Scanner scanner = new Scanner(System.in);            String input = scanner.nextLine();            out.writeUTF(input);            out.flush();            if("exit".equals(input)){                //获取服务器端断开连接的信息                String serverInput = in.readUTF();                System.out.println(serverInput);                //客户端断开连接                System.out.println("客户端关闭连接");                in.close();                out.close();                socket.close();                break;            }        }    }}
package socketTest;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class SocketServer{    private ServerSocket serverSocket;    private ExecutorService threadPool;    private static final int THREADCOUNT = 5;    public static void main(String[] arg){        SocketServer socketServer = new SocketServer();        try {            socketServer.initParam(6644);            socketServer.getRequest();        } catch (Exception e) {            socketServer.threadPool.shutdown();            e.printStackTrace();        }    }    //初始化参数    public void initParam(int port) throws Exception{        this.serverSocket = new ServerSocket(port);        this.threadPool = Executors.newFixedThreadPool(THREADCOUNT);    }    //获取客户端请求    public void getRequest() throws IOException{        while (true) {            Socket socket = this.serverSocket.accept();            SocketThread socketThread = new SocketThread(socket);            threadPool.execute(socketThread);        }    }}
package socketTest;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;public class SocketThread implements Runnable {    private Socket socket;    private DataInputStream in;//通信输入流    private DataOutputStream out;//通信输出流    public SocketThread(Socket socket){        try {            this.socket = socket;            this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));            this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public void run() {        try {            String clientInput;            while((clientInput = in.readUTF())!=null){                System.out.println(clientInput);                if("exit".equals(clientInput)){                    out.writeUTF("服务器已关闭连接");                    out.close();                    in.close();                    socket.close();                    System.out.println("服务端关闭连接");                    break;                }            }        } catch (IOException e) {            e.printStackTrace();        }    }}
1 0