UDP和TCP通信

1.UDP服务端和客户端 “一对一” 和“ 多对多” 传送和接收信息

  • 一对一
import org.junit.Test;

import java.net.*;

public class TestUdp {

    //服务端
    @Test
    public  void serverTest() throws Exception {

        DatagramSocket socket=new DatagramSocket(8888);
        //创建一个数据包对象接收数据
        byte[] buffer=new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        //等待接收数据
        socket.receive(packet);

        //取出数据
        int len = packet.getLength();
        String rs = new String(buffer,0,len);
        System.out.println(rs);
        socket.close();

    }
    //客户端
    @Test
    public  void clientTest() throws Exception {
        //创建发送对象(人)
        DatagramSocket socket = new DatagramSocket();
        //创建一个数据包对象封装数据
        byte[] buffer="我是一个快乐的韭菜盒子".getBytes();
        DatagramPacket packet=new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),8888);
        //3。发送数据
        socket.send(packet);
        socket.close();
    }

}

  • 多对多(组播)
import org.junit.Test;

import java.net.*;
import java.util.Scanner;
//测试组播
public class TestUdpgroupBrocastt {



    //服务端
    @Test
    public  void serverTest() throws Exception {

      //  DatagramSocket socket=new DatagramSocket(8888);
        //创建一个组播对象接口
        MulticastSocket socket=new MulticastSocket(9999);
        //把当前接收端加到一个组播组中,绑定对应的组播消息的组播IP
        //joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
        socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.0.1.1"),9999),
                NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));
        //创建一个数据包对象接收数据
        byte[] buffer=new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        while (true) {
            //等待接收数据
            socket.receive(packet);
            //取出数据
            int len = packet.getLength();
            String rs = new String(buffer,0,len);
            System.out.println(rs);
            //获取发送端的IP和端口
            System.out.println("收到了来自:"+packet.getAddress()+",对方接口是:"+packet.getPort()+"的消息:"+rs);
        }
      //  socket.close();

    }



    //客户端
    @Test
    public  void clientTest() throws Exception {
        //创建发送对象(人)
        DatagramSocket socket  = new DatagramSocket();
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入内容:");
            String msg = sc.nextLine();
            if("exit".equals(msg)){
                socket.close();
                return;
            }
            //创建一个数据包对象封装数据
            byte[] buffer=msg.getBytes();
            DatagramPacket packet=new DatagramPacket(buffer,buffer.length,InetAddress.getByName("224.0.1.1"),9999);
            //3。发送数据
            socket.send(packet);
        }

    }

}

  1. TCP通信
//基础通信(存在的问题:当服务端接收不到数据就会报连接异常)
import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TestTcp {

    @Test
    public  void client() throws  Exception{
        //1.创建socket接口
        Socket socket = new Socket("127.0.0.1",7777);
        //2.从socket通信管道中得到一个字节输出流,负责发送给数据
        OutputStream os = socket.getOutputStream();
        //3.把低级的字节流包装成打印流
        PrintStream ps = new PrintStream(os);
        //4.发送消息
        ps.println("我是TCP 客户端,你要一起玩吗?");
        ps.flush();

    }

    @Test
    public  void server() throws IOException {
        //1.注册接口
        ServerSocket sserverocket = new ServerSocket(7777);
        //2.必须调用accept接口,,等待客户端的socket连接请求
        Socket socket = sserverocket.accept();
        //3.从socket中得到一个字节输入流

        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        //3.按行读取数据
        String msg;
        if((msg= br.readLine())!=null){
            System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
        }


    }
}
  • TCP通信-多发多收消息
    待解决问题:1.目前服务端是单线程的,每次只能处理一个客户端的消息。(加入一个循环)
    2.客户端的端口只有一个(解决方式如下图)
    Allow multiple instances
package com.practies;

import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TestThreadTcp {
    @Test
    public  void client() throws IOException {
        Socket socket = new Socket("127.0.0.1",7777);
        OutputStream os = socket.getOutputStream();
        PrintStream ps = new PrintStream(os);
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请说:");
            String msg = sc.nextLine();
            ps.println(msg);
            ps.flush();
        }
        //关闭端口
        ///socket.close();
    }

    @Test
    public  void server(){
        try {
            System.out.println("服务器启动成功");
            ServerSocket ss=new ServerSocket(7777);
            while(true){
                //从socket管道接受数据
                Socket socket= ss.accept();
                //创建线程开始处理
                new ServerReaderThread(socket).start();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建线程方法
    public   class  ServerReaderThread extends Thread{
        private  Socket socket;
        public  ServerReaderThread(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String msg;
                while ((msg=br.readLine())!=null){
                    System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

  • 上述代码存在的问题:当客户端反复发送数据时,服务端会一直创建线程,线程太多时,会占用系统cpu、资源等等,因此引入线程池
package com.practies;

import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.*;

public class TestThreadTcp2 {
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,
            6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    @Test
    public  void client() throws IOException {
        Socket socket = new Socket("127.0.0.1",7777);
        OutputStream os = socket.getOutputStream();
        PrintStream ps = new PrintStream(os);
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请说:");
            String msg = sc.nextLine();
            ps.println(msg);
            ps.flush();
        }
        //关闭端口
        ///socket.close();
    }

    @Test
    public  void server(){
        //使用一个静态变量记住一个线程池对象
        try {
            System.out.println("服务器启动成功");
            ServerSocket ss=new ServerSocket(7777);
            while(true){
                //从socket管道接受数据
                Socket socket= ss.accept();
                //创建线程开始处理
                System.out.println(socket.getRemoteSocketAddress()+"它来了,上线了!");
                Runnable target = new ServerReadRunnable(socket);
                pool.execute(target);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建线程方法
    public  class ServerReadRunnable implements Runnable {
        private  Socket socket;
        public  ServerReadRunnable(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String msg;
                while ((msg=br.readLine())!=null){
                    System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }

}

  • TCP通信实战-即时通信(类似弹幕)
import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;

public class TestThreadTcp3 {
  //定义一个静态的list集合存储当前全部在线的socket
   public static List<Socket> allOnlineSockets= new ArrayList<Socket>();

    @Test
    public  void client() throws IOException {
        Socket socket = new Socket("127.0.0.1",7777);
        //创建一个独立的线程负责这个客户端的读消息
        new ClientReadThread(socket).start();
        OutputStream os = socket.getOutputStream();
        PrintStream ps = new PrintStream(os);
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请说:");
            String msg = sc.nextLine();
            ps.println(msg);
            ps.flush();
        }
        //关闭端口
        ///socket.close();
    }

    @Test
    public  void server(){
        try {
            System.out.println("服务器启动成功");
            ServerSocket ss=new ServerSocket(7777);
            while(true){
                //从socket管道接受数据
                Socket socket= ss.accept();
                allOnlineSockets.add(socket);
                //创建线程开始处理
                new  ServerReaderThread(socket).start();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建线程方法
    public   class  ServerReaderThread extends Thread{
        private  Socket socket;
        public  ServerReaderThread(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String msg;
                while ((msg=br.readLine())!=null){
                    System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
                    //把消息发给全部的管道
                    sendMsgtoAll(msg);
                }
            } catch (IOException e) {
                System.out.println(socket.getRemoteSocketAddress()+",下线了,下次再来哦");
                allOnlineSockets.remove(socket);
            }
        }
    }
    public void sendMsgtoAll(String msg ) throws IOException {
        for (Socket socket : allOnlineSockets) {
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println(msg);
            ps.flush();
        }
    }


    public  class ClientReadThread extends Thread {
        private  Socket socket;
        public   ClientReadThread(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String msg;
                while ((msg=br.readLine())!=null){
                    System.out.println("收到消息了。。。。。"+msg);
                }
            } catch (IOException e) {
                System.out.println("服务端把你踢出去了");
            }

        }
    }

}

  1. BS
    (1)、之前的客户端都是什么样的 。其实就是CS架构,客户端实需要我们自己开发实现的。
    (2)、BS结构是什么样的,需要开发客户端吗? 浏览器访问服务端,不需要开发客户端。
package com.practies;

import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class BSServerTest {
    @Test
    public  void server(){
        try {
            System.out.println("服务器启动成功");
            ServerSocket ss=new ServerSocket(7777);
            while(true){
                //从socket管道接受数据
                Socket socket= ss.accept();
                //创建线程开始处理
                new ServerReaderThread(socket).start();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建线程方法
    public   class  ServerReaderThread extends Thread{
        private  Socket socket;
        public  ServerReaderThread(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {

            try {
                PrintStream ps = new PrintStream(socket.getOutputStream());
                //响应HTTP格式
                ps.println("HTTP/1.1 200 OK");
                ps.println("Content-Type:text/html;charset=UTF-8");
                ps.println();//按照HTTP要求必须发一个空行
                ps.println("<span style='color:red;font-size:90px'>哈哈</span>");
                ps.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }


        }
    }
}

package com.practies;

import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.*;

public class BSServerTest2 {
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,
            6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());


    @Test
    public  void server(){
        //使用一个静态变量记住一个线程池对象
        try {
            System.out.println("服务器启动成功");
            ServerSocket ss=new ServerSocket(7777);
            while(true){
                //从socket管道接受数据
                Socket socket= ss.accept();
                //创建线程开始处理
                System.out.println(socket.getRemoteSocketAddress()+"它来了,上线了!");
                Runnable target = new ServerReadRunnable(socket);
                pool.execute(target);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建线程方法
    public  class ServerReadRunnable implements Runnable {
        private  Socket socket;
        public  ServerReadRunnable(Socket socket){
            this.socket=socket;
        }

        @Override
        public void run() {
            try {
                PrintStream ps = new PrintStream(socket.getOutputStream());
                //响应HTTP格式
                ps.println("HTTP/1.1 200 OK");
                ps.println("Content-Type:text/html;charset=UTF-8");
                ps.println();//按照HTTP要求必须发一个空行
                ps.println("<span style='color:red;font-size:90px'>哈哈</span>");
                ps.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值