赞
踩
目录
TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议,用于在计算机网络中传输数据。它是互联网协议套件(TCP/IP)中的核心协议之一。
TCP协议提供了一种可靠的、有序的、面向字节流的数据传输机制,它能够确保数据的完整性、可靠性和顺序性。TCP协议在应用层之上建立了一种端到端的通信,通过使用IP协议进行数据包的传输。
TCP协议的特点和功能包括:
由于TCP协议具有可靠性和有序性,以及对拥塞的控制能力,它被广泛用于可靠数据传输的应用中,如网页浏览、文件传输、电子邮件、远程登录和数据通信等。
Socket(套接字)是计算机网络编程中用于实现网络通信的一种编程接口或抽象概念。它提供了一种标准的接口,使应用程序能够通过网络与其他计算机进行通信。
Socket可以看作是应用程序与网络之间的一个通信端点,类似于电话中的插座。通过Socket,应用程序可以创建、连接、发送和接收数据,以实现网络通信。
Socket通常使用TCP/IP协议栈作为底层网络协议,但也可以与其他协议一起使用,如UDP(User Datagram Protocol)和ICMP(Internet Control Message Protocol)等。
在网络编程中,通常需要以下几个步骤来使用Socket:
通过Socket编程接口,开发人员可以轻松实现网络通信功能,包括客户端和服务器之间的数据交换、网络服务的实现、远程操作和网络应用的开发等。Socket提供了一种灵活而强大的机制,使得网络通信变得简单而高效。
在明白TCP协议和Socket概念的前提下,想要实现用Java程序来进行TCP编程其实不难,首先再重复一下编程中的相关概念:
接下来,创建两个程序,一个充当服务器端,另一个充当客户端;服务器端会主动监听某个指定的端口,客户端必须主动连接服务器的 IP 地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个 TCP 连接,双方后续就可以随时发送和接收数据。
服务端程序的实现:
- import java.net.*;
- import java.io.*;
-
- public class TcpServer {
- public static void main(String[] args) {
- try {
- ServerSocket ss = new ServerSocket(8001); // 驻守在8001端口
- Socket s = ss.accept(); // 阻塞,等到有客户端连接上来
- System.out.println("welcome to the java world");
- InputStream ips = s.getInputStream(); // 有client连上来,打开输入流
- OutputStream ops = s.getOutputStream(); // 打开输出流
- // 同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
-
- ops.write("Hello, Client!".getBytes()); // 输出一句话给客户端
-
- BufferedReader br = new BufferedReader(new InputStreamReader(ips));
- // 从客户端读取一句话
- System.out.println("Client said: " + br.readLine());
-
- ips.close();
- ops.close();
- s.close();
- ss.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
客户端程序的实现:
- import java.io.BufferedReader;
- import java.io.DataOutputStream;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.Socket;
-
- public class TcpClient {
- public static void main(String[] args) {
- try {
- Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001); //需要服务端先开启
-
- // 同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
- InputStream ips = s.getInputStream(); //开启通道的输入流
- BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
-
- OutputStream ops = s.getOutputStream(); //开启通道的输出流
- DataOutputStream dos = new DataOutputStream(ops);
-
- BufferedReader brKey = new BufferedReader(new InputStreamReader(System.in));
- while (true) {
- String strWord = brKey.readLine();
- if (strWord.equalsIgnoreCase("quit")) {
- break;
- } else {
- System.out.println("I want to send: " + strWord);
- // 向服务端发送数据(使用输出流)
- dos.writeBytes(strWord + System.getProperty("line.separator"));
- // 打印接收到的数据(使用输入流)
- System.out.println("Server said: " + brNet.readLine());
- }
-
- }
-
- dos.close();
- brNet.close();
- brKey.close();
- s.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
分别启动服务端和客户端程序,演示效果如下:
注意:服务端需要先于客户端启动,否则客户端因连接不到指定的进程而报错。同时输入输出流还可以传各种类型的数据,详情请参考 Java 的各种 I/O 流实现。
实际场景中,一个服务端往往可以支持多个客户端的连接,为多个客户端提供服务。如下图所示:
此处,为了实现上述想法,可以通过多线程改进一下服务端程序的实现:
- import java.net.*;
-
- public class TcpServer2 {
- public static void main(String[] args) {
- try {
- ServerSocket serverSocket = new ServerSocket(8001);
- while (true) {
- Socket socket = serverSocket.accept();
- System.out.println("监听到 client 连接...");
- // 启动一个线程
- new Thread(new Worker(socket)).start();
- }
- //ss.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
Worker.class 类的详情如下:
- import java.net.*;
- import java.io.*;
-
- class Worker implements Runnable {
-
- Socket socket;
-
- public Worker(Socket socket) {
- this.socket = socket;
- }
-
- public void run() {
- try {
- System.out.println("Worker 已经启动...");
- InputStream ips = socket.getInputStream();
- OutputStream ops = socket.getOutputStream();
-
- BufferedReader br = new BufferedReader(new InputStreamReader(ips));
- DataOutputStream dos = new DataOutputStream(ops);
- while (true) {
- String strWord = br.readLine();
- System.out.println("client said:" + strWord + ":" + strWord.length());
- if (strWord.equalsIgnoreCase("quit")){
- break;
- }
- String strEcho = strWord + " 666";
- // dos.writeBytes(strWord +"---->"+ strEcho +"\r\n");
- System.out.println("server said:" + strWord + "---->" + strEcho);
- dos.writeBytes(strWord + "---->" + strEcho + System.getProperty("line.separator"));
- }
- br.close();
- // 关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
- dos.close();
- socket.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
分别启动服务端和客户端1和2后的演示效果如下:
在客户端1,输入Hi:
在客户端2,输入Hello:
服务端的输出如下:
至此,Java 基于 TCP 的 Socket 编程结束。有关 Java 基于 UDP 的 Socket 编程,可以参考我的这篇文章:《Java 基于 UDP 的 Socket 编程》。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。