Java实现TCP编程

        首先我们先来了解什么是TCP:

        1.TCP协议(传输控制协议)是面向连接的可靠的协议,是允许系统通过Internet进行通信的标准,它定义了如何建立和维护应用程序可以通过其交换数据的网络对话;保证了数据的传递,并保证数据包的发送顺序与发送数据包的顺序相同,是OSI层中的传输层协议,通过传输和确保通过支持网络和Internet传递消息来在远程计算机之间创建连接。

        2.在明白TCP协议这个概念的前提下我们要想实现用Java程序来进行TCP编程其实不难,只需要我们理清相关概念:
        ip:唯一的标识Internet上的某台计算机,在Java程序中通过InetAddress类获取IP

        端口号:可以理解为正在计算机上运行的进程,不同的进程有不同的端口号

        Socket:这是一个比较抽象的概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。
        3.明白了上面的内容后我们就可以开始一个简单的局域网内的TCP编程了,我们在使用Socket进行网络编程时,本质上就是两个进程之间的网络通信,其中两个进程一个为服务器端,另一个充当客户端;服务器端会主动监听某个指定的端口,客户端必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。

服务器端

        编写服务器端程序:Java标准库提供了ServerSocket来实现对指定IP和指定端口的监听。ServerSocket的典型实现代码如下:

//服务器端
public class TcpTest {
	public static void main(String[] args) {
		// 1.创建服务器端的ServerSocket,指明自己的端口号
		try (ServerSocket server = new ServerSocket(1516);
				// 2.调用accept表示监听客户端的socket
				Socket client = server.accept();
				// 3.获取一个输入流
				InputStream in = client.getInputStream();
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8))) {
			// 4.获取输入流中的数据
			String str = null;
			while ((str = reader.readLine()) != null) {
				System.out.println(str);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

    客户端

        相比服务器端,客户端程序就要简单很多。一个典型的客户端程序如下:

//客户端
public class TcpTest {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        try {
            //1.创建Socket对象,指明服务器IP和端口号
            socket = new Socket("192.168.254.159", 1516);
            //2.获取一个输出流用于输出数据
            out = socket.getOutputStream();
            //3.写出数据的操作(这里也可以用转换流OutputStreamWriter)
            out.write("你好,我是小明".getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源的关闭
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace(); } } } }}

        4.观察服务器端和客户端程序,这个过程大致可分为四步:

        ①我们首先在创建ServerSocket的对象时在参数中传入了一个端口号,这样是为了让客户端能够通过此端口找到它的服务并成功连接,在客户端中我们同样创建一个Socket对象并将要连接的目标主机ip和端口传入其中,这样服务器端才监听得到。

        ②两端连接成功后就返回一个Socket实例,这个Socket实例就是用来和刚连接的客户端进行通信的。因为TCP是一种基于流的协议,因此,Java标准库使用InputStream和OutputStream来封装Socket的数据流,这样我们使用Socket的流,和普通IO流类似。

        ③我们可以使用Socket实例的getInputStream()和getOutputStream()建立流的对象来进行文件或数据的发送与接收。

        ④在我们进行完数据的传递不需要再维持连接时要记得关闭输入输出流和socket流

        5.如果你试过上面的程序就会发现它进行过一次传输后就会自动关闭连接,而且你的客户端数据发送成功后没有得到服务器端的任何反馈,那么我们可以对这个程序做个小小的完善:

//服务器端
public class TcpTest2 {
	public static void main(String[] args) {
		try (ServerSocket server = new ServerSocket(1617);
				Socket socket = server.accept();
				InputStream in = socket.getInputStream();
				OutputStream out = new FileOutputStream(new File("D:\\Eclipse file\\aaa\\a2.jpg"))) {
			byte[] buff = new byte[1024];
			int len;

			while ((len = in.read(buff)) != -1) {
				out.write(buff, 0, len);
			}

			// 接收到图片后向客户端反馈
			try (BufferedWriter writer = new BufferedWriter(
					new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8))) {
				writer.write("你好,我已成功收到图片!");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
//客户端发送数据到服务器,并且要得到服务器发送成功的反馈

public class TcpTest2 {
    public static void main(String[] args) throws IOException {
        Socket client = new Socket("192.168.254.159", 1617);
        OutputStream out = client.getOutputStream();
        FileInputStream in = new FileInputStream(new File("C:\\Users\\肖\\Pictures\\Saved Pictures\\73621770bf3138ea4cd3b07cc5d2caa0b31855d5.jpg"));
        byte[] buff = new byte[1024];
        int len = -1;
        while ((len = in.read(buff)) != -1) {
            out.write(buff, 0, len);
        }
        client.shutdownOutput();

        //接收来自于服务器端的反馈,并显示在控制台
        InputStream sin = client.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(sin));
        String line = null;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        out.close();
        in.close();
        client.close();
        sin.close();
        reader.close();
    }
}

        上面的程序是客户端向服务端发送了一张图片,在执行完程序后我们会看到服务端会向客户端反馈 "你好,我已成功收到图片!",客户端会打印此消息到控制台。
        其中我们要注意到的点是:客户端在向服务端发送完数据后要有个 client.shutdownOutput();的操作,用这个动作来告诉服务器端我发送完了,然后服务器端才会继续向下执行反馈。再就是这个程序还是只能执行一次的,而一般的服务器是一直在运行的,所以我们也可以给服务器端的程序外层嵌套一个while(true)的循环来让它一直accept()监听端口。

你可能感兴趣的:(java,tcp/ip,网络)