网络编程UDP与TCP

网络编程三要素

1 IP地址:InetAddress: 网络中设备的标识,不易记忆,可用主机名
IP地址 = 网络地址+主机地址
A类IP地址:第一段号码为网络地址,剩下的三段号码为本地计算机的号码
1.0.0.1—127.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)
(2)127.X.X.X是保留地址,用做循环测试用的。
B类IP地址:前二段号码为网络地址,剩下的二段号码为本地计算机的号码
128.0.0.1—191.255.255.254 172.16.0.0—172.31.255.255是私有地址。
C类IP地址:前三段号码为网络地址,剩下的一段号码为本地计算机的号码
192.0.0.1—223.255.255.254 192.168.x.X是私有地址
2 端口号: 用于标识进程的逻辑地址,不同进程的标识
物理端口 网卡口
逻辑端口 我们指的就是逻辑端口
a:每个网络程序都会有一个逻辑端口
b:用于标识进程的逻辑地址,不同进程的标识
c:有效端口:065535(两个字节),其中01023系统使用或保留端口。
3 传输协议: 通讯的规则常见协议:TCP,UDP
UDP
将数据源和目的封装成数据包中,不需要建立连接;
每个数据报的大小在限制在64k;
因无连接,是不可靠协议;
不需要建立连接,速度快
TCP
建立连接,形成传输数据的通道;
在连接中进行大数据量传输;
需要连接所以是可靠协议;
必须建立连接,效率会稍低

UDP

        //1.创建客户端UDP的Socket
        DatagramSocket ds = new DatagramSocket();
        //2.封装数据   DatagramPacket数据报包 数据报包用来实现无连接包投递服务。
        //2.1创建数据报包
        //DatagramPacket( byte[] buf, int length, InetAddress address,int port)
        //构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
        byte[] bytes = "你好UPD,我来了".getBytes();
        InetAddress address = InetAddress.getByName("192.168.47.1");
        //参数3 服务器ip
        //参数4:服务端socket的端口号
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, 9999);
        //3.发送数据,发送数据报包
        ds.send(dp);
        //4.释放资源
        ds.close();


 //创建UDP服务端
        //DatagramSocket( int port)
        //创建数据报套接字并将其绑定到本地主机上的指定端口。
        //创建服务端的Sokcet并暴露端口号
        DatagramSocket ds = new DatagramSocket(9999);
        //创建空的数据报包,来接收发送过来的报包
        //DatagramPacket( byte[] buf, int length)
        //构造 DatagramPacket,用来接收长度为 length 的数据包。
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        //接收数据
        System.out.println("服务器已经开启...等待接收数据");
        //receive(dp) 方法的接收
        //从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。
        //数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
        //此方法在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。
        //如果信息比包的长度长,
        ds.receive(dp); //阻塞的方法,如果数据没过来,就等待在这里。
        //从数据报包中取数据
        byte[] data = dp.getData();
        //获取数据报包中数据的实际长度
        int length = dp.getLength();
        //再来获取发送方的IP
        String ip = dp.getAddress().getHostAddress();
        //把字节数据转换成字符串
        String s = new String(data, 0, length);
        System.out.println(ip+":给你发来消息,内容是:"+s);
        //释放资源
        ds.close();

AB互发消息

public class A {
    public static void main(String[] args) {
        //创建子线程开启服务器,来接收消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //创建服务端的Socket,并暴露端口号
                    DatagramSocket ds = new DatagramSocket(9999);
                    System.out.println("A服务器已经开启,等待连接");
                    while (true) {
                        //接收发送过来的数据
                        byte[] bytes = new byte[1024];
                        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                        ds.receive(dp);
                        //从数据报包中取出数据
                        byte[] data = dp.getData();
                        int length = dp.getLength();
                        //取发送者的IP
                        String ip = dp.getAddress().getHostAddress();
                        String s = new String(data, 0, length);
                        System.out.println(ip + ":B给你发来消息:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //在主线程给对方发消息
        sendMsg();
    }
    private static void sendMsg() {
        try {
            //创建客户端的socket
            DatagramSocket ds = new DatagramSocket();
            //创建键盘录入对象
            BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                System.out.println("请输入消息");
                String s = bfr.readLine();
                if (s.equals("886")) {
                    break;
                }
                byte[] bytes = s.getBytes();
                //创建数据报包
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.47.1"), 8888);
                //发送数据
                ds.send(dp);
            }
            //释放资源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




//

public class B {
    public static void main(String[] args) {
        //创建子线程开启服务器,来接收消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //创建服务端的Socket,并暴露端口号
                    DatagramSocket ds = new DatagramSocket(8888);
                    System.out.println("B服务器已经开启,等待连接");
                    while (true) {
                        //接收发送过来的数据
                        byte[] bytes = new byte[1024];
                        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                        ds.receive(dp);
                        //从数据报包中取出数据
                        byte[] data = dp.getData();
                        int length = dp.getLength();
                        //取发送者的IP
                        String ip = dp.getAddress().getHostAddress();
                        String s = new String(data, 0, length);
                        System.out.println(ip + ":A给你发来消息:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //在主线程给对方发消息
        sendMsg();
    }
    private static void sendMsg() {
        try {
            //创建客户端的socket
            DatagramSocket ds = new DatagramSocket();
            //创建键盘录入对象
            BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                System.out.println("请输入消息");
                String s = bfr.readLine();
                if (s.equals("886")) {
                    break;
                }
                byte[] bytes = s.getBytes();
                //创建数据报包
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.47.1"), 9999);
                //发送数据
                ds.send(dp);
            }
            //释放资源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

TCP

//TCP客户端 Socket类
//TCP服务端 ServerSocket类

        //创建客户端的sokcet
        //Socket(InetAddress address, int port)
        //创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
        //Socket(String host, int port)
        //创建一个流套接字并将其连接到指定主机上的指定端口号。
        //参数:服务器ip和端口
        Socket socket = new Socket("192.168.47.1", 9999);
        //获取通道中的输出流
        OutputStream out = socket.getOutputStream();
        //发送数据
        out.write("你好TCP".getBytes());
        //释放资源
        socket.close();



 //1.创建服务端的Socket 并暴露端口号
        ServerSocket ss = new ServerSocket(9999);
        //2.侦听客户端的连接。
        //Socket accept ()
       //侦听并接受到此套接字的连接。
        //阻塞式方法。accept()侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
        System.out.println("服务器已经开启,等待连接。。。。");
        Socket socket = ss.accept();
        //.获取通道中的输入流
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        //转换成字符串
        String s = new String(bytes, 0, len);
        System.out.println(s);
        //服务器关闭
        ss.close();

//客户端键盘录入服务器控制台输出

public class TCPClient {
    public static void main(String[] args) throws IOException {
        //A:
        //案例演示:
        //客户端键盘录入服务器控制台输出
        Socket sk = new Socket("192.168.47.1", 6666);
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        while (true){
            System.out.println("请输入消息");
            String msg= bfr.readLine();
            //发送给服务端
            OutputStream out= sk.getOutputStream();
            out.write(msg.getBytes());
            if ("886".equals(msg)) {
                break;
            }
        }
        //释放资源
        bfr.close();
    }
}





//
public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。");
        Socket sk = ss.accept();
        //循环读取客户端发来的消息
        while (true){
            InputStream in = sk.getInputStream();
            String ip = sk.getInetAddress().getHostAddress();
            byte[] bytes = new byte[1024];
            int len = in.read(bytes);
            String s = new String(bytes, 0, len);
            if(s.equals("886")){
                break;
            }
            System.out.println(ip+":给你发来消息内容是:"+s);
        }
        ss.close();
    }
}


客户端键盘录入服务器写到文本文件

    Socket sk = new Socket("192.168.47.1", 6666);
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        String line=null;
        OutputStream out = sk.getOutputStream();
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        while ((line=bfr.readLine())!=null){
            System.out.println("请输入消息");
            //可以把通道中的字节流,包装成字符流
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
            if("886".equals(line)){
                break;
            }
        }
        sk.close();
//


 //服务器接收客户端发来的消息,把消息保存到文本文件中
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务端已经开启,等待连接。。。");
        Socket sk = ss.accept();
        //把通道中的输入流包装成字符流
        InputStream in = sk.getInputStream();
        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        String line = null;
        BufferedWriter bfw = new BufferedWriter(new FileWriter("msg.txt"));
        while ((line = bfr.readLine()) != null) {
            if("886".equals(line)){
                break;
            }
            //写入文本文件
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
            System.out.println(line);
        }
        ss.close();

从文件读取内容,发送给服务端,服务端输出到控制台展示

        Socket sk = new Socket("192.168.47.1", 6666);
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        BufferedReader bfr = new BufferedReader(new FileReader("msg.txt"));
        //可以把通道中的字节流,包装成字符流
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        String line=null;
        while ((line=bfr.readLine())!=null){
            //读取一行写到通道中
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //释放资源
        sk.close();
        bfr.close();


//


  //服务端读取消息展示
        ServerSocket ss= new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。。");
        //侦听客户端
        Socket sk = ss.accept();
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //把通道中的字节输入流,包装字符流
        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        //读取消息展示
        String line=null;
        while ((line=bfr.readLine())!=null){
            System.out.println(line);
        }
        ss.close();

客户端读取文本文件中的消息---->服务端读取法过来的消息,保存到文本文件中

    Socket sk = new Socket("192.168.47.1", 6666);
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //客户端读取文件
        BufferedReader bfr = new BufferedReader(new FileReader("demo.java"));
        //包装通道中的字节输出流,为字符流
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        String line=null;
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //释放资源
        sk.close();
        bfr.close();


//
  //服务端读取消息展示
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。。");
        //侦听客户端
        Socket sk = ss.accept();
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //把通道中的字节输入流,包装成字符
        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        String line=null;
        BufferedWriter bfw = new BufferedWriter(new FileWriter("demo_upload.java"));
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        ss.close();
        bfw.close();

手动写标记告诉服务端

  Socket sk = new Socket("192.168.47.1", 6666);
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //客户端读取文件
        BufferedReader bfr = new BufferedReader(new FileReader("demo.java"));
        //包装通道中的字节输出流,为字符流
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        String line=null;
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //客户上传完了,告诉服务端一声
        //手动写一个标记给服务端
        bfw.write("over");
        bfw.newLine();
        bfw.flush();
        //读取服务端的反馈
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(s);
        //释放资源
        sk.close();
        bfr.close();


//


   //服务端读取消息展示
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。。");
        //侦听客户端
        Socket sk = ss.accept();
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //把通道中的字节输入流,包装成字符
        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        String line=null;
        BufferedWriter bfw = new BufferedWriter(new FileWriter("demo_upload.java"));
        while ((line=bfr.readLine())!=null){
            //服务端读取到标记
            if("over".equals(line)){
                break;
            }
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //服务器给客户端,反馈一个上传成功
        out.write("客户端你好!我服务端保存成功".getBytes());
        ss.close();
        bfw.close();

我们可以调用一个方法
void shutdownInput ()
此套接字的输入流置于“流的末尾”。
void shutdownOutput ()
禁用此套接字的输出流。

        Socket sk = new Socket("192.168.47.1", 6666);
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //客户端读取文件
        BufferedReader bfr = new BufferedReader(new FileReader("demo.java"));
        //包装通道中的字节输出流,为字符流
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        String line=null;
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
       k.shutdownOutput();
        //读取服务端的反馈
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(s);
        //释放资源
        sk.close();
        bfr.close();



//



    //服务端读取消息展示
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。。");
        //侦听客户端
        Socket sk = ss.accept();
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //把通道中的字节输入流,包装成字符
        BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
        String line=null;
        BufferedWriter bfw = new BufferedWriter(new FileWriter("demo_upload.java"));
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //服务器给客户端,反馈一个上传成功
        out.write("客户端你好!我服务端保存成功".getBytes());
        ss.close();
        bfw.close();

一个服务端,连接多个客户端

  //客户端给服务端上传文本文件。
        //客户端读取文本文件中的消息---->服务端读取法过来的消息,保存到文本文件中
        //客户端,从文件读取内容,发送给服务端,服务端输出到控制台展示
        Socket sk = new Socket("127.0.0.1", 6666);
        //获取通道中的输入输出流
        InputStream in = sk.getInputStream();
        OutputStream out = sk.getOutputStream();
        //客户端读取文件
        BufferedReader bfr = new BufferedReader(new FileReader("demo.java"));
        //包装通道中的字节输出流,为字符流
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        String line=null;
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
  sk.shutdownOutput();
        //读取服务端的反馈
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(s);
        //释放资源
        sk.close();
        bfr.close();
        

//
   ServerSocket ss = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接。。。。");
        //一个服务端,连接多个客户端
        //写个死循环侦听多个客户端
        int i=1;
        while (true){
            Socket sk = ss.accept();
            System.out.println((i++)+"个客户已经连接。");
            //多个客户端给服务端上传文件,我们在服务端给每个连接上来的客户端,开启一个单独的线程,来处理文件上传,
            //也就是说多个客户端并发的上传,用户体验就好
            //把建立的sk通道,传到线程中,去在线程中处理上传
            new UploadThread(sk).start();
        }





//
public class UploadThread extends Thread {
    private Socket sk;
    public UploadThread(Socket sk) {
        this.sk=sk;
    }
    @Override
    public void run() {
        System.out.println("线程在执行");
        try {
            //获取通道中的输入输出流
            InputStream in = sk.getInputStream();
            OutputStream out = sk.getOutputStream();
            //把通道中的字节输入流,包装成字符
            BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
            String line = null;
            //注意文件名,多个客户端上传文件,防止覆盖现象,注意取一个随机的文件名。
            BufferedWriter bfw = new BufferedWriter(new FileWriter(System.currentTimeMillis()+"demo_upload.java"));
            while ((line = bfr.readLine()) != null) {
                bfw.write(line);
                bfw.newLine();
                bfw.flush();
            }
            //服务器给客户端,反馈一个上传成功
            out.write("客户端你好!我服务端保存成功".getBytes());
            //bfw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值