|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 moc 于 2019-8-29 21:02 编辑
1、简介
1. 网络编程含义:
用Java语言实现计算机间数据的信息传递和资源共享。
2. 网络编程模型:
① OSI(Open System Interconnection开放系统互连)参考模型(7 层模型)
应用层 》表示层 》会话层 》传输层 》网络层 》数据链路层 》物理层
② TCP/IP参考模型
应用层 》传输层 》网际层 》链路层 》物理层
3. 网络编程三要素:
① IP地址
》点分十进制记法,私有地址不在互联网上使用,用于局域网。
》A类地址: 1.0.0.1—126.255.255.254 --- 保留给政府机构{10.X.X.X是私有地址}
》B类地址:128.0.0.1—191.255.255.254 --- 中等规模的公司{172.16.0.0—172.31.255.255是私有地址、169.254.X.X是保留地址}
》C类地址:192.0.0.1—223.255.255.254 --- 任何需要的人{192.168.X.X是私有地址}
》D类地址:224.0.0.1—239.255.255.254
》E类地址:240.0.0.1—255.255.255.254
》127.X.X.X为保留地址,用做循环测试用的。
② 端口
同一个主机内不同应用程序的标识,范围:0-65535。其中0-1024不建议使用。
③ 协议
》TCP:建立数据通道,全双工,无边界流,效率低,面向连接,可靠
》UDP:无数据通道,全双工,数据打包,效率高,无连接,不可靠
4. Socket机制
① 通信两端都应该有Socket对象;
② 客户端和服务器通过对 Socket 对象的写入和读取来进行通信;
2、UDP通讯
1. 相关API
InetAddress类: --- 互联网协议 (IP) 地址
public static InetAddress getByName(String host) ----> 在给定主机名的情况下确定主机的 IP 地址; 主机名可以是机器名,也可是其 IP 地址的文本表示形式。
public String getHostName() ----------------------------> 获取此 IP 地址的主机名。
public String getHostAddress() --------------------------> 返回 IP 地址字符串(文本表现形式)。
DatagramSocket类: --- 表示用来发送和接收数据报包(UDP)的套接字
public DatagramSocket() ----------------------------------- --> 构造数据报套接字并将其绑定到本地主机上任何可用的端口。
public DatagramSocket(int port) -----------------------------> 创建数据报套接字并将其绑定到本地主机上的指定端口,IP 地址由内核选择。
public DatagramSocket(int port, InetAddress laddr) ------> 创建数据报套接字,将其绑定到指定的本地地址。
public void receive(DatagramPacket p) ---------------------> 从此套接字接收数据报包。
public void send(DatagramPacket p) ------------------------> 从此套接字发送数据报包。
DatagramPacket类: --- 表示数据报包,用来实现无连接包投递服务。
public DatagramPacket(byte[] buf, int length) ------------> 构造 DatagramPacket,用来接收长度为 length 的数据包。
public DatagramPacket(byte[] buf, int length, InetAddress address, int port) -----> 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
public InetAddress getAddress() -----------------------------> 返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
public byte[] getData() --------------------------------------> 返回将要发送或接收到的数据缓冲区内容。
public int getLength() ------------------------------------------> 返回将要发送或接收到的数据的长度。
2. UDP协议发送数据
步骤:
① 创建发送端Socket对象;
② 创建数据,并把数据打包;
③ 调用Socket对象的发送方法发送数据包;
④ 释放资源。
- public class UdpSendDemo {
- public static void main(String[] args) throws IOException {
- // 创建发送端Socket对象
- DatagramSocket ds = new DatagramSocket();
- // 创建数据,并把数据打包
- byte[] bys = "UDP,你好!".getBytes(); // 创建数据
- int length = bys.length; // 长度
- InetAddress address = InetAddress.getByName("192.168.12.92"); // IP地址对象
- int port = 10086; // 端口
- DatagramPacket dp = new DatagramPacket(bys, length, address, port);
- // 调用Socket对象的发送方法发送数据包
- ds.send(dp);
- // 释放资源
- ds.close();
- }
- }
复制代码 3. UDP协议接受数据
步骤:
① 创建接收端Socket对象;
② 创建一个数据包(接收容器);
③ 调用Socket对象的接收方法接收数据;
④ 解析数据包,并显示在控制台;
⑤ 释放资源。
- public class UdpReceiveDemo {
- public static void main(String[] args) throws IOException {
- // 创建接收端Socket对象
- DatagramSocket ds = new DatagramSocket(10086);
- // 创建一个数据包(接收容器)
- byte[] bys = new byte[1024];
- int length = bys.length;
- DatagramPacket dp = new DatagramPacket(bys, length);
- // 调用Socket对象的接收方法接收数据
- ds.receive(dp); // 阻塞式
- // 解析数据包,并显示在控制台
- InetAddress address = dp.getAddress(); // 获取对方的ip
- String ip = address.getHostAddress();
- byte[] bys2 = dp.getData(); // 获取数据缓冲区
- int len = dp.getLength(); // 获取数据的实际长度
- String s = new String(bys2, 0, len);
- System.out.println(ip + "传递的数据是:" + s);
- // 释放资源
- ds.close();
- }
- }
复制代码 4. 多线程结合收发UDP数据包
- // ***********发送UDP数据报类
- public class UdpSendThread implements Runnable {
- private DatagramSocket ds;
- public SendThread(DatagramSocket ds) {
- this.ds = ds;
- }
- @Override
- public void run() {
- try {
- // 封装键盘录入数据
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- String line = null;
- while ((line = br.readLine()) != null) {
- if ("886".equals(line)) {
- break;
- }
- // 创建数据并打包
- byte[] bys = line.getBytes();
- DatagramPacket dp = new DatagramPacket(bys, bys.length,
- InetAddress.getByName("192.168.12.255"), 12306);
- // 发送数据
- ds.send(dp);
- }
- // 释放资源
- ds.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- // ***********接受UDP数据报类
- public class ReceiveThread implements Runnable {
- private DatagramSocket ds;
- public ReceiveThread(DatagramSocket ds) {
- this.ds = ds;
- }
- @Override
- public void run() {
- try {
- while (true) {
- // 创建一个包裹
- byte[] bys = new byte[1024];
- DatagramPacket dp = new DatagramPacket(bys, bys.length);
- // 接收数据
- ds.receive(dp);
- // 解析数据
- String ip = dp.getAddress().getHostAddress();
- String s = new String(dp.getData(), 0, dp.getLength());
- System.out.println("from " + ip + " data is : " + s);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- // ***********测试类
- public class ChatRoom {
- public static void main(String[] args) throws IOException {
- DatagramSocket dsSend = new DatagramSocket();
- DatagramSocket dsReceive = new DatagramSocket(12306);
- SendThread st = new SendThread(dsSend);
- ReceiveThread rt = new ReceiveThread(dsReceive);
- Thread t1 = new Thread(st);
- Thread t2 = new Thread(rt);
- t1.start();
- t2.start();
- }
- }
复制代码 3、TCP通讯
1. 相关API
Socket类: --- TCP客户端套接字
public Socket(InetAddress address, int port) --------> 创建一个流套接字并将其连接到指定 IP 地址的指定端口号
public InetAddress getInetAddress() -----------------> 返回套接字连接的地址。
public InputStream getInputStream() ----------------> 返回此套接字的输入流。
public OutputStream getOutputStream() ------------> 返回此套接字的输出流。
public void shutdownOutput() --------------------------> 通知对方套接字写入结束。
ServerSocket类: --- TCP服务器套接字
public ServerSocket(int port) --------------------------> 创建绑定到特定端口的服务器套接字。
public Socket accept() ----------------------------------> 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
2. TCP客户端实现
步骤:
① 创建发送端的Socket对象;
② 这一步如果成功,就说明连接已经建立成功;
③ 获取输出流写数据,获取输入流读数据 ;
④ 释放资源;
以下以客户端向服务器上传文件为例:
注意:
读取文本文件时可以以null作为结束信息的,TCP流通道不能以null结束;
于是① 自定义结束标记;
② Socket对象提供了一种解决方案,public void shutdownOutput()
- public class UdpUploadClient {
- public static void main(String[] args) throws IOException {
- // 创建客户端Socket对象
- Socket s = new Socket("192.168.12.92", 11111);
- // 封装文本文件
- BufferedReader br = new BufferedReader(new FileReader("123.txt"));
- // 封装通道内流
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
- String line = null;
- while ((line = br.readLine()) != null) { // 阻塞
- bw.write(line);
- bw.newLine();
- bw.flush();
- }
- //自定义一个结束标记
- //bw.write("over");
- //bw.newLine();
- //bw.flush();
-
- //Socket提供了一个终止,它会通知服务器:客户端数据传输已结束
- s.shutdownOutput();
- // 接收反馈
- BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
- String client = brClient.readLine(); // 阻塞
- System.out.println(client);
- // 释放资源
- br.close();
- s.close();
- }
- }
复制代码 3. TCP服务器实现
步骤:
① 创建接收端的Socket对象;
② 监听客户端连接。返回一个对应的Socket对象;
③ 获取输出流写数据,获取输入流读数据 ;
④ 释放资源。
- public class UploadServer {
- public static void main(String[] args) throws IOException {
- // 创建服务器端的Socket对象,并绑定端口
- ServerSocket ss = new ServerSocket(11111);
- // 监听客户端连接
- Socket s = ss.accept(); // 阻塞
- // 封装通道内的流
- BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
- // 封装文本文件
- BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
- String line = null;
- while ((line = br.readLine()) != null) { // 阻塞
- // if("over".equals(line)){ // 采用自定义“over”结束符
- // break;
- // }
- bw.write(line);
- bw.newLine();
- bw.flush();
- }
- // 给出反馈
- BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
- bwServer.write("文件上传成功");
- bwServer.newLine();
- bwServer.flush();
- // 释放资源
- bw.close();
- s.close();
- }
- }
复制代码 4. TCP服务器多线程实现并发
支持服务器能够被多个客户端连接。
- // ********** 服务器线程类
- public class UserUdpThread implements Runnable {
- private Socket s;
- public UserUdpThread (Socket s) {
- this.s = s;
- }
- @Override
- public void run() {
- try {
- // 封装通道内的流
- BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
- // 封装文本文件
- // BufferedWriter bw = new BufferedWriter(newFileWriter("Copy.txt"));
- // 为了防止名称冲突
- String newName = System.currentTimeMillis() + ".txt";
- BufferedWriter bw = new BufferedWriter(new FileWriter(newName));
- String line = null;
- while ((line = br.readLine()) != null) { // 阻塞
- bw.write(line);
- bw.newLine();
- bw.flush();
- }
- // 给出反馈
- BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
- bwServer.write("文件上传成功");
- bwServer.newLine();
- bwServer.flush();
- // 释放资源
- bw.close();
- s.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- // ********** 服务器
- public class UploadUdpServer {
- public static void main(String[] args) throws IOException {
- // 创建服务器Socket对象
- ServerSocket ss = new ServerSocket(11111);
- while (true) {
- Socket s = ss.accept();
- new Thread(new UserUdpThread(s)).start();
- }
- }
- }
复制代码 |
评分
-
查看全部评分
|