黑马程序员技术交流社区

标题: 【石家庄中心】网络编程_基于UDP及TCP协议的数据传输 [打印本页]

作者: 水煮牛蛙    时间: 2018-4-23 15:51
标题: 【石家庄中心】网络编程_基于UDP及TCP协议的数据传输
本帖最后由 小石姐姐 于 2018-4-25 15:56 编辑

网络编程_基于UDP及TCP协议的数据传输

* 网络编程:
*                 通过我们编写的程序让两个不同的设备可以进行交互,可以进行数据的传输,
*                两个设备本身是无法传输数据的,通过软件或程序才可以进行不同设备之间的传输,
*                说到网络编程,就不得不说Socket(套接字)
*Socket(套接字):
*                        写在不同设备间的程序也可称之为Socket
*                        我们所说的网络编程也可称为Socket编程或套接字编程
*                        不同程序之间的数据传输就是不同Socket之间的传输
* 通信:数据在两个Socket之间的是通过IO流进行的;
*
* 通信三要素:
*                 1. IP地址:InterAddress 现在的IP地址用32为2进制数表示,也就是4个字节
*                                 设备在网络中的地址
*                         ipconfig 命令在windows的dos命令行可以显示:
*                                                                                 网卡/ip地址
*                         在dos命令行中ip地址使用的是点分十进制法,来表示的,可以更方便的去记忆和修改ip地址
*                        //命令为  ipconfig                        

*                         1.1 IP分为 :
*                                      * 网络地址
*                                      * 主机地址(内网地址)
*                                 这两个地址 确保了全球网络的唯一性,但是4字节(IPV4)的网络地址,相对于现在来说已经太小了,
*                                 因此有了现在的IPv6 它是IPv4的六倍,也就是16个字节
*                         1.2 IP地址根据用途及安全级别的不同还分为:
*                                                         1.公共地址(可以通过Internet直接访问)
*                                                         2.私有地址(内部网地址,局域网地址)
*
*                 2.端口号:  用于标识进程的逻辑地址,不同进程的表示
*                         网络编程:就是两个设备之间的软件进行交互
*                                   每个软件运行都要有一个进程,端口号指的就是这个进程的地址,设备中有很多网络程序,因此要指定一个
*                                 具体的 网络程序,所以需要进程的地址,也就是端口号.
*                 3.协议
*                         其实就是一种规则和规范
*                         有很多的网络协议:后期会接触两种协议
*                                         1.UOP协议
*                                         2.TCP协议:通过三次握手完成连接,是可靠协议;
*                                         
*                         UDP协议:
*                                         将数据源和目的地封装成数据包,不需要建立连接了;
*                                         每个数据包的大小限制在64k;无连接,是不可靠的协议;
*                                         不需要建立连接,速度快;
*                         TCP协议:
*                                         建立连接,行成传输数据的通道;在连接中进行大数据量传输;
*                                         通过三次握手完成连接,是可靠协议;
*                                         必须建立连接,效率会稍低
         域名和主机名一样:
                         1.网络上叫域名
                         2.局域网中叫主机名

----------------------------------------------------
>>>>>>  UDP 协议接收 / 发送 数据    <<<<<<

   UDP协议收发注意事项:
*                 1.端口号错误,数据可以正常发出,不会抛出异常,但是接受不到数据
*                 2.接受端口号不可以重名(多个程序运行时)
*                 重复会报错:"java.net.BindException: Address already in use: Cannot bind"
*                                    意思为端口号已绑定;
*                 第一个运行此端口可程序不会报错,后运行该端口的程序会报错
*                 3.因此在设定接受端端口号时,避免跟其它程序的端口号冲突;
*
* 1.数据发送时,接收端的IP,端口都在数据报包中
* 2.接受数据时,接收端口号在数据接收套接字中
* 3.发送的时候会通过IP找到接受端设备,在统过端口号,将数据送到指定的程序
* 4.想后去发送端的信息需要通过解析接受包,使用数据报包的方法获取;
------------
案例:
         1.数据接收
         2.数据发送

------------

>>>>>>>  接收端程序

package com.jobday12;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
* 使用UDP协议接受数据:
*                 1.创建接受端Socket对象
*                 2.接受数据
*                 3.解析数据
*                 4.输出数据
*                 5.释放资源
*
* DatagramSocket 类的接收数据方法
*                         对象名.receive(DatagramPacket dp);
*                         1.发送数据
*                         2.使用该方法时,如果内有数据传进来,程序会一直在该处 < 阻塞  >;
*
*
* DatagramPacket 类的获取方法:
*                 InetAddress getAddress()
*                 //返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
                  
                   ************************
                   *  问题: 不明白                        *
                   *  1.接受数据时获取发送端的IP *
                   *  2.发送数据时获取接受端的IP *
                   ************************
        byte[] getData():
             //获取接受的数据
        int getLength()
                //返回将要发送或接收到的数据的长度。
               int getPort()
                       //返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。(获取接受或发送端的端口,相对当前程序)
                  
*/
public class 接受端_UDP协议接受数据 {
        public static void main(String[] args) throws IOException {
                 //1.创建接受端Socket对象
                //创建指定端口号的数据接收对象(与发送端指定的接受端口号要一致)
                DatagramSocket ds = new DatagramSocket(888);
                //2.接受数据
                //定义接受数据的容器
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys,bys.length);
               
                //接受数据
                ds.receive(dp);//此处会阻塞,等待数据传入
               
                 //3.解析数据
                //获取发送端的IP地址
                InetAddress address = dp.getAddress();
                //获取接受数据的实际长度
                int leng = dp.getLength();
                //获取数据
                bys = dp.getData();
                 //4.输出数据
                System.out.println("发送端IP:  "+address);
                System.out.println("接受数据长度: "+leng);
                System.out.println("接受到的数据 : "+new String(bys,leng));
                 //5.释放资源
        }
}
-------------
>>>>>> 发送端程序

package com.jobday12;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
*使用UDP协议发送数据
*                1.创建发送端Socket对象
*                2.创建数据并打包
*                3.发送数据
*                4.释放资源
*
*数据发送接收类:
*
* DatagramSocket 类: 此类表示用来发送和接受数据,基于UDP协议的(此类表示用来发送和接收数据报包的套接字。)
*                        
*                 1.        DatagramSocket():创建Socket对象并随即分配端口号(随机给自己分配一个端口号)
*                 2.        DatagramSocket(int port):创建Socket对象并制定端口号(int port,指的是自己的端口号)
*                 如果是创建发送端对象的话使用方法1就行(随机生成就行),因为是发送数据因此自己的端口号知不知道都行
*                 如果是接受数据,就要制定自己的端口号,因为发送端发送数据是指定了端口,因此接受端就要有指定的端口号(不可以随机生成)
*                        
* 数据报包类:
*                 DatagramPacket : 此类表示数据报包
*                 构造:
*                         DatagramPacket(byte[] buf, int length, InetAddress address, int port)
*                         //构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
*                         byte[] buf : 数据
*                         int length : 数据包中数据的长度(字节数组中数据的实际长度)
*                         InetAddress address :目的地设备的IP地址
*                         int port : 接收端端口号
*
*/
public class 发送端_UDP协议发送数据 {

        public static void main(String[] args) throws IOException {
               
                //1.创建发送端Socket对象
                DatagramSocket ds = new DatagramSocket();
               
                //2.创建数据并打包
               
                //要发送的数据
                byte[] bys = "hello,udp,im coming!".getBytes();
               
                //数长度
                int leng = bys.length;
               
                //接收端IP对象 ,此处是通过本机主机名,开获取的IP对象,因为接受端也在次电脑上(实际中获取的是接受断点的IP对象)
                InetAddress address = InetAddress.getByName("USERCHI-D484R2Q");
               
                //接受端口
                int port = 888;  //此处随机定义了一个接收端接受程序的端口号
               
                //创建数据包报对象,打包数据
                DatagramPacket dp = new DatagramPacket(bys,leng,address,port);
               
                //3.发送数据
                ds.send(dp);//此方法发送数据是以个DatagramPacket类的对象(也就是数据报包)
                InetAddress add = dp.getAddress();
                System.out.println(add);
                //4.释放资源
                ds.close();
        }

}
----------------------------------------------------------------------------
>>>>>>>>>  TCP 协议 发送_接受数据   <<<<<<<<<<<<<<<

>>>>>>>>  发送端
package com.jobday12;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/*
* 使用TCP协议送数据
                 创建发送端Socket对象(创建连接)
                 获取输出流对象
                  发送数据
                  释放资源
  注意:
          没有接收端的话,运行发送端,就会报错,连接异常
         java.net.ConnectException

*/
public class TCP协议_发送数据 {

        public static void main(String[] args) throws IOException {
                //创建发送端Socket对象(创建连接)
                Socket s = new Socket(InetAddress.getByName("USERCHI-D484R2Q"),10086);
                 //        获取输出流对象
                OutputStream os = s.getOutputStream();
                  //发送数据
                String str = "hello tcp,im comming!!!";
                os.write(str.getBytes());
                  //释放资源
                s.close();
        }

}
--------------------------
>>>>>>>>>  接收端
package com.jobday12;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/*
         使用TCP协议接受数据
                         创建接受端Socket对象
                         监听(阻塞)
                         获取输入流对象
                         获取数据
                         输出数据
                         释放资源
                        
        Socket 是客户端套接字
         接收端要用 ,服务端Socket
         服务端为: ServerSocket(int port)  //构造
方法:
         ServerSocket(int port)
         Socket accept()  //侦听并接受到此套接字的连接.获取一个客户端套接字
                                           //ServerSocket 本身没有读取功能,因此需要获取一个
                                           //Socket,利用的它的读取功能获取发送端的数据
                                          
通过获取到的Socket对象的方法可以获取发送端的IP地址
                        
*/
public class TCP协议_接受端 {

        public static void main(String[] args) throws IOException {
                        //创建接受端Socket对象
                ServerSocket ss = new ServerSocket(10086);
                        //监听(此处会一直阻塞,知道有)
                Socket s = ss.accept();//一直等待客户端发来的链接,收到数据后会返回一个Socket对象
                                //通过Socket获得数据和客户端的数据
               
                InetAddress inetAddress = s.getInetAddress();
                System.out.println(inetAddress.getHostAddress());
                //获取发送端的IP地址
                        //获取输入流对象
                InputStream is = s.getInputStream();
                        //获取数据
                byte[] bys = new byte[1024];
                int len;
                len = is.read(bys);
                        //输出数据
                System.out.println(new String(bys,0,len));
                        //释放资源
                is.close();//关闭输入流
                //服务器端不需要关闭
        }

}






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2