鱼C论坛

 找回密码
 立即注册
查看: 2956|回复: 4

[学习笔记] Java033-网络编程

[复制链接]
发表于 2019-1-14 20:09:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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对象的发送方法发送数据包;
        ④ 释放资源。
  1. public class UdpSendDemo {
  2.         public static void main(String[] args) throws IOException {
  3.                 // 创建发送端Socket对象
  4.                 DatagramSocket ds = new DatagramSocket();

  5.                 // 创建数据,并把数据打包
  6.                 byte[] bys = "UDP,你好!".getBytes();  // 创建数据
  7.                 int length = bys.length;  // 长度
  8.                 InetAddress address = InetAddress.getByName("192.168.12.92");  // IP地址对象
  9.                 int port = 10086;        // 端口
  10.                 DatagramPacket dp = new DatagramPacket(bys, length, address, port);

  11.                 // 调用Socket对象的发送方法发送数据包
  12.                 ds.send(dp);

  13.                 // 释放资源
  14.                 ds.close();
  15.         }
  16. }
复制代码
3. UDP协议接受数据
步骤:
        ① 创建接收端Socket对象;
        ② 创建一个数据包(接收容器);
        ③ 调用Socket对象的接收方法接收数据;
        ④ 解析数据包,并显示在控制台;
        ⑤ 释放资源。
  1. public class UdpReceiveDemo {
  2.         public static void main(String[] args) throws IOException {
  3.                 // 创建接收端Socket对象
  4.                 DatagramSocket ds = new DatagramSocket(10086);

  5.                 // 创建一个数据包(接收容器)
  6.                 byte[] bys = new byte[1024];
  7.                 int length = bys.length;
  8.                 DatagramPacket dp = new DatagramPacket(bys, length);

  9.                 // 调用Socket对象的接收方法接收数据
  10.                 ds.receive(dp); // 阻塞式

  11.                 // 解析数据包,并显示在控制台
  12.                 InetAddress address = dp.getAddress();  // 获取对方的ip
  13.                 String ip = address.getHostAddress();
  14.                 byte[] bys2 = dp.getData();   // 获取数据缓冲区
  15.                 int len = dp.getLength();     // 获取数据的实际长度
  16.                 String s = new String(bys2, 0, len);
  17.                 System.out.println(ip + "传递的数据是:" + s);

  18.                 // 释放资源
  19.                 ds.close();
  20.         }
  21. }
复制代码
4. 多线程结合收发UDP数据包
  1. // ***********发送UDP数据报类
  2. public class UdpSendThread implements Runnable {
  3.         private DatagramSocket ds;
  4.         public SendThread(DatagramSocket ds) {
  5.                 this.ds = ds;
  6.         }

  7.         @Override
  8.         public void run() {
  9.                 try {
  10.                         // 封装键盘录入数据
  11.                         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  12.                         String line = null;
  13.                         while ((line = br.readLine()) != null) {
  14.                                 if ("886".equals(line)) {
  15.                                         break;
  16.                                 }

  17.                                 // 创建数据并打包
  18.                                 byte[] bys = line.getBytes();
  19.                                 DatagramPacket dp = new DatagramPacket(bys, bys.length,
  20.                                                                         InetAddress.getByName("192.168.12.255"), 12306);

  21.                                 // 发送数据
  22.                                 ds.send(dp);
  23.                         }

  24.                         // 释放资源
  25.                         ds.close();
  26.                 } catch (IOException e) {
  27.                         e.printStackTrace();
  28.                 }
  29.         }
  30. }
  31. // ***********接受UDP数据报类
  32. public class ReceiveThread implements Runnable {
  33.         private DatagramSocket ds;
  34.         public ReceiveThread(DatagramSocket ds) {
  35.                 this.ds = ds;
  36.         }

  37.         @Override
  38.         public void run() {
  39.                 try {
  40.                         while (true) {
  41.                                 // 创建一个包裹
  42.                                 byte[] bys = new byte[1024];
  43.                                 DatagramPacket dp = new DatagramPacket(bys, bys.length);

  44.                                 // 接收数据
  45.                                 ds.receive(dp);

  46.                                 // 解析数据
  47.                                 String ip = dp.getAddress().getHostAddress();
  48.                                 String s = new String(dp.getData(), 0, dp.getLength());
  49.                                 System.out.println("from " + ip + " data is : " + s);
  50.                         }
  51.                 } catch (IOException e) {
  52.                         e.printStackTrace();
  53.                 }
  54.         }
  55. }
  56. // ***********测试类
  57. public class ChatRoom {
  58.         public static void main(String[] args) throws IOException {
  59.                 DatagramSocket dsSend = new DatagramSocket();
  60.                 DatagramSocket dsReceive = new DatagramSocket(12306);

  61.                 SendThread st = new SendThread(dsSend);
  62.                 ReceiveThread rt = new ReceiveThread(dsReceive);

  63.                 Thread t1 = new Thread(st);
  64.                 Thread t2 = new Thread(rt);

  65.                 t1.start();
  66.                 t2.start();
  67.         }
  68. }
复制代码
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()
  1. public class UdpUploadClient {
  2.          public static void main(String[] args) throws IOException {
  3.                 // 创建客户端Socket对象
  4.                 Socket s = new Socket("192.168.12.92", 11111);

  5.                 // 封装文本文件
  6.                 BufferedReader br = new BufferedReader(new FileReader("123.txt"));
  7.                 // 封装通道内流
  8.                 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

  9.                 String line = null;
  10.                 while ((line = br.readLine()) != null) { // 阻塞
  11.                         bw.write(line);
  12.                         bw.newLine();
  13.                         bw.flush();
  14.                 }
  15.                 //自定义一个结束标记
  16.                 //bw.write("over");
  17.                 //bw.newLine();
  18.                 //bw.flush();
  19.                
  20.                 //Socket提供了一个终止,它会通知服务器:客户端数据传输已结束
  21.                 s.shutdownOutput();

  22.                 // 接收反馈
  23.                 BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
  24.                 String client = brClient.readLine();   // 阻塞
  25.                 System.out.println(client);

  26.                 // 释放资源
  27.                 br.close();
  28.                 s.close();
  29.         }
  30. }
复制代码
3. TCP服务器实现
步骤:
        ① 创建接收端的Socket对象;
        ② 监听客户端连接。返回一个对应的Socket对象;
        ③ 获取输出流写数据,获取输入流读数据 ;
        ④ 释放资源。
  1. public class UploadServer {
  2.         public static void main(String[] args) throws IOException {
  3.                 // 创建服务器端的Socket对象,并绑定端口
  4.                 ServerSocket ss = new ServerSocket(11111);

  5.                 // 监听客户端连接
  6.                 Socket s = ss.accept(); // 阻塞

  7.                 // 封装通道内的流
  8.                 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
  9.                 // 封装文本文件
  10.                 BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));

  11.                 String line = null;
  12.                 while ((line = br.readLine()) != null) { // 阻塞
  13.                         // if("over".equals(line)){   // 采用自定义“over”结束符
  14.                         // break;
  15.                         // }
  16.                         bw.write(line);
  17.                         bw.newLine();
  18.                         bw.flush();
  19.                 }

  20.                 // 给出反馈
  21.                 BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
  22.                 bwServer.write("文件上传成功");
  23.                 bwServer.newLine();
  24.                 bwServer.flush();

  25.                 // 释放资源
  26.                 bw.close();
  27.                 s.close();
  28.         }
  29. }
复制代码
4. TCP服务器多线程实现并发
支持服务器能够被多个客户端连接。
  1. // **********  服务器线程类
  2. public class UserUdpThread implements Runnable {
  3.         private Socket s;
  4.         public UserUdpThread (Socket s) {
  5.                 this.s = s;
  6.         }

  7.         @Override
  8.         public void run() {
  9.                 try {
  10.                         // 封装通道内的流
  11.                         BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
  12.                         // 封装文本文件
  13.                         // BufferedWriter bw = new BufferedWriter(newFileWriter("Copy.txt"));

  14.                         // 为了防止名称冲突
  15.                         String newName = System.currentTimeMillis() + ".txt";
  16.                         BufferedWriter bw = new BufferedWriter(new FileWriter(newName));

  17.                         String line = null;
  18.                         while ((line = br.readLine()) != null) { // 阻塞
  19.                                 bw.write(line);
  20.                                 bw.newLine();
  21.                                 bw.flush();
  22.                         }

  23.                         // 给出反馈
  24.                         BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
  25.                         bwServer.write("文件上传成功");
  26.                         bwServer.newLine();
  27.                         bwServer.flush();

  28.                         // 释放资源
  29.                         bw.close();
  30.                         s.close();
  31.                 } catch (IOException e) {
  32.                         e.printStackTrace();
  33.                 }
  34.         }
  35. }
  36. // **********  服务器
  37. public class UploadUdpServer {
  38.         public static void main(String[] args) throws IOException {
  39.                 // 创建服务器Socket对象
  40.                 ServerSocket ss = new ServerSocket(11111);

  41.                 while (true) {
  42.                         Socket s = ss.accept();
  43.                         new Thread(new UserUdpThread(s)).start();
  44.                 }
  45.         }
  46. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
拳头捶奶 + 5 + 5 + 3

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-5-28 21:24:51 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-6-26 20:06:09 | 显示全部楼层
不错的内容 能写多一点就好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-8-27 21:07:53 | 显示全部楼层
public class UserUdpThread implements Runnable {
        private Socket s;
        public UserThread(Socket s) {
                this.s = s;
        }

构造函数拼写错误l
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-29 21:03:12 | 显示全部楼层
erh 发表于 2019-8-27 21:07
public class UserUdpThread implements Runnable {
        private Socket s;
&#1 ...

谢谢提醒,已修正。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 10:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表