文章目录
- 第一部分:网络编程前置知识
- 1.1 IP地址:网络的“门牌号”
- 1.2 端口号:设备的“房间号”
- 1.3 网络协议:通信的“语言规则”
- 第二部分:Java中的ServerSocket与Socket类
- 2.1 Socket:通信的“客户端”
- 2.2 ServerSocket:通信的“服务端”
- 2.3 通信模型图解
- 第三部分:代码结构与示例
- 3.1 基础示例:单次问候通信
第一部分:网络编程前置知识
在学习Java网络编程之前,我们需要了解几个基础概念,这就像盖房子前要先认识砖头和水泥一样。
1.1 IP地址:网络的“门牌号”
IP地址是互联网上每台设备的唯一标识,用于定位设备的位置。就像寄快递需要收件人的地址一样,网络通信也需要知道对方的IP地址。
- IPv4:最常见的格式,如
192.168.1.1,由4组0-255的数字组成。 - IPv6:新一代地址格式,如
2001:0db8:85a3::8a2e:0370:7334,能提供更多的地址数量。
1.2 端口号:设备的“房间号”
一台设备(比如你的电脑)可以同时运行多个网络程序(如浏览器、微信、游戏)。端口号就是用来区分这些不同程序的“房间号”。
- 范围:0-65535
- 常见端口:
- 80:HTTP网页服务
- 443:HTTPS安全网页服务
- 3306:MySQL数据库
- 8080:常用的开发测试端口
1.3 网络协议:通信的“语言规则”
协议规定了数据如何打包、发送、接收和解析,确保通信双方能互相理解。
- TCP(传输控制协议):可靠的、面向连接的协议。像打电话,需要先建立连接,保证数据不丢失、不错序。适合文件传输、网页浏览等。
- UDP(用户数据报协议):不可靠的、无连接的协议。像发短信,直接发送,不保证对方一定能收到。适合视频直播、在线游戏等对实时性要求高的场景。
Java网络编程主要使用TCP协议,这也是我们接下来要学习的重点。
第二部分:Java中的ServerSocket与Socket类
Java提供了java.net包来支持网络编程,其中两个最核心的类就是ServerSocket和Socket。
2.1 Socket:通信的“客户端”
Socket类代表客户端的连接端点。你可以把它想象成一部电话机,用于向服务器发起连接和进行数据交换。
主要方法:
Socket(String host, int port):构造方法,连接到指定主机和端口。getInputStream():获取输入流,用于接收服务器发来的数据。getOutputStream():获取输出流,用于向服务器发送数据。close():关闭连接。
基本使用流程(客户端):
- 创建Socket对象,指定服务器的IP和端口。
- 通过Socket获取输入输出流。
- 使用流进行数据读写。
- 通信完成后关闭连接。
2.2 ServerSocket:通信的“服务端”
ServerSocket类运行在服务器上,像总机接线员,等待客户端的连接请求。
主要方法:
ServerSocket(int port):构造方法,在指定端口上监听。accept():阻塞方法,等待客户端连接。一旦有客户端连接,就返回一个与该客户端通信的Socket对象。close():停止监听。
基本使用流程(服务端):
- 创建ServerSocket对象,绑定到特定端口。
- 调用
accept()方法等待客户端连接。 - 接收到连接后,通过返回的Socket对象与客户端通信。
- 通信完成后关闭连接。
2.3 通信模型图解
一个典型的“客户端-服务器”模型工作流程如下:
客户端发起连接:客户端 (Client) → 服务器 (Server)
- 客户端通过
new Socket(服务器IP, 端口)发起连接请求。
- 客户端通过
服务器等待连接:服务器 (Server) → 等待连接…
- 服务器端的
ServerSocket.accept()方法阻塞等待,直到有客户端连接。
- 服务器端的
建立连接:客户端 ↔ 服务器
- 连接建立后,服务器
accept()方法返回一个用于与该客户端通信的Socket对象。
- 连接建立后,服务器
客户端发送数据:客户端 → 服务器
- 客户端通过
Socket.getOutputStream()获取输出流,向服务器发送数据。
- 客户端通过
服务器接收并处理数据:服务器 → 处理数据
- 服务器通过
Socket.getInputStream()获取输入流,读取客户端发来的数据。 - 服务器处理数据(例如,打印、计算、查询数据库等)。
- 服务器通过
服务器回复数据:服务器 → 客户端
- 服务器通过
Socket.getOutputStream()获取输出流,向客户端发送回复数据。
- 服务器通过
客户端接收回复:客户端 → 接收数据
- 客户端通过
Socket.getInputStream()获取输入流,读取服务器的回复。
- 客户端通过
关闭连接:客户端 ↔ 服务器
- 通信完成后,双方调用各自
Socket或ServerSocket的close()方法关闭连接。
- 通信完成后,双方调用各自
第三部分:代码结构与示例
以下是本文涉及的代码文件结构。您可以将自己的代码填充到对应的位置,我会用// 你的代码写在这里这样的注释来标记。
3.1 基础示例:单次问候通信
这个示例展示最简单的“客户端发送一句问候,服务器接收并回复”流程。
服务端代码框架 (SimpleServer.java)
packageorg.atguigu;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.Scanner;//服务端代码publicclassB{publicstaticvoidmain(String[]args)throwsIOException{//监听本地端口号,等待客户端建立连接ServerSocketserverSocket=newServerSocket(303);System.out.println("等待连接中:");Socketsocket=serverSocket.accept();System.out.println("连接成功");//接下来的数据发送和接受都通过socket对象来讲进行接收或者获取,使用输入流和输出流//输出流,用来向对面发送数据OutputStreamout=socket.getOutputStream();//输入流,用来获取输入的数据InputStreamin=socket.getInputStream();Scannerscanner=newScanner(System.in);while(true){//将获取到的数据进行解析byte[]buffer=newbyte[1024];intlen=in.read(buffer);Stringstr=newString(buffer,0,len);System.out.println("已经收到数据:"+str);System.out.print("你说: ");Stringreply=scanner.nextLine();if("exit".equals(reply))break;//向客户端发送数据,告诉客户端我已经收到了你发送的消息out.write(reply.getBytes());}socket.close();serverSocket.close();}}客户端代码框架
packageorg.atguigu;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.net.Socket;importjava.util.Scanner;//发送方代码publicclassA{publicstaticvoidmain(String[]args)throwsIOException{//定位需要发送的目标ip地址和端口号Socketsocket=newSocket("127.0.0.1",303);//定义输入输出流//输出流,用来向对面发送数据OutputStreamout=socket.getOutputStream();//输入流,用来获取输入的数据InputStreamin=socket.getInputStream();Scannerscanner=newScanner(System.in);while(true){System.out.print("你说: ");Stringmsg=scanner.nextLine();if("exit".equals(msg))break;out.write(msg.getBytes());//将获取到的数据进行解析byte[]buffer=newbyte[1024];intlen=in.read(buffer);Stringstr=newString(buffer,0,len);System.out.println(str);}socket.close();}}