从一对一聊天到群聊超详解案例,学习Java网络编程之TCP与UDP协议

27 篇文章 0 订阅
1 篇文章 0 订阅
 

网络编程

   实现网络互连的不同计算机上运行的程序间可以进行 数据交换。
  • 计算机网络
       由一些相互连接的、自治的计算机组成的集合
  • 网络编程的概念
  • 网络七层结构(五层结构)
  • 网络通信三要素
    • ip(计算机标识)
    • 端口(计算机上不同服务的标识)
    • 协议
      • UDP 
        • 不面向连接 不可靠
      • TCP
        • 面向连接的 可靠的(三次握手)
public static void main(String[] args) throws UnknownHostException {
    InetAddress inetAddress =InetAddress.getByName("LAPTOP-70SMTMJN");
    //
    System.out.println(inetAddress);
    //获取主机名称
    String hostName = inetAddress.getHostName();
    System.out.println(hostName);
    //获取主机IP地址
    String hostAddress = inetAddress.getHostAddress();
    System.out.println(hostAddress);
}

 

Socket通信

  • Socket套接字:
  • 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
    • 通信原理:
      • 数据在两个Socket间通过IO传输
    • socke常见构造函数:
      • API是个宝贝
    • Socket常见方法:
      • getOutputStream()  返回此套接字的输出流
  • TCP协议开发(面向连接,可靠协议)

    • 基本通讯
/*----------------服务器端-----------------------*/

//创建出服务器Scoket对象
ServerSocket serverSocket =new ServerSocket(8888);


System.out.println("服务器启动成功");
//服务器应该时刻知道客户端是否连接
Socket socket =serverSocket.accept();


//读取客户端数据
DataInputStream in =new DataInputStream(socket.getInputStream());
System.out.println(in.readUTF());
//写数据
DataOutputStream out =new DataOutputStream(socket.getOutputStream());
out.writeUTF("服务器:客户端你好");

/*----------------客户端-----------------------*/

Socket socket =new Socket("localhost",8888);
    //客户端写数据
    DataOutputStream out =new DataOutputStream(socket.getOutputStream());
    out.writeUTF("客户端说:服务器你好");
    DataInputStream in =new DataInputStream(socket.getInputStream());
    System.out.println(in.readUTF());

 

  • 案例_一对一聊天

    • 添加线程,让用户在聊天的时候不需要等待对方回复也是可以成功发送消息
    • 将服务器与客户端的读与写全部加上while(true)死循环
 
/**
* @Auther: etc
* @Date: 2019/8/5 10:27
* @Description:  服务器端
*
*         **如果客户端连不上服务器,那就去看看别人能不能ping通你
*         如果不能可能是防火墙限制了,关掉就好
*         如果可以,那就很有可能是端口被占用了,改一下端口号
*
*
*/
public class Sever
{
    public static Scanner sc =new Scanner(System.in);
    public static void main(String[] args) throws IOException
    {
        //创建出服务器serverSocket对象
        ServerSocket serverSocket =new ServerSocket(10010);
        System.out.println("服务器启动成功");


        //服务器应该时刻知道客户端是否连接
        Socket socket =serverSocket.accept();


        SeverThread severThread =new SeverThread(socket);
        severThread.start();




        while(true)
        {
            //写数据
            DataOutputStream out =new DataOutputStream(socket.getOutputStream());
            out.writeUTF("服务器:"+sc.next());
        }


    }
}
//单读读取数据的线程
class SeverThread extends Thread
{
    private Socket socket;
    public SeverThread(Socket socket)
    {
        this.socket=socket;
    }
    @Override
    public void run() {


        //读取客户端数据
        try {
            while (true) {
                DataInputStream in = new DataInputStream(socket.getInputStream());


                System.out.println(in.readUTF());
            }


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


    }
}


/*---------------------------------------------------------------------------*/


/**
* @Auther: etc
* @Date: 2019/8/5 10:54
* @Description:
*/
public class Client
{
    public static Scanner sc =new Scanner(System.in);


    public static void main(String[] args) throws IOException
    {
        Socket socket =new Socket("192.168.28.38",10010);


        ClientThread clientThread=new ClientThread(socket);
        clientThread.start();


        while (true)
        {
            //客户端写数据
            DataOutputStream out =new DataOutputStream(socket.getOutputStream());
            out.writeUTF("客户端:"+sc.nextLine());
        }


    }
}


class ClientThread extends Thread
{
    private Socket socket;
    public ClientThread(Socket socket)
    {
        this.socket=socket;
    }
    @Override
    public void run() {


        try {
            while(true)
            {
                DataInputStream in = new DataInputStream(socket.getInputStream());
                System.out.println(in.readUTF());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

  • 案例_群聊

    • 客户端代码依旧不变
    • 服务器代码修改:
      • 使用socketList .add(socket)来记录连接的对象,一个客户端对应一个对象
      • 客户端之间发送消息:遍历集合 socketList(使用泛型),如果对应的 Socket不是自己的,那就转发消息
 

/**
* @Auther: etc
* @Date: 2019/8/5 10:27
* @Description:  服务器端
*/
public class Sever
{


    public static Scanner sc =new Scanner(System.in);




    //服务器应该时刻知道客户端是否连接
    public static List<Socket> socketList =new ArrayList<Socket>();




    public static void main(String[] args) throws IOException
    {
        //创建出服务器serverSocket对象
        ServerSocket serverSocket =new ServerSocket(8886);
        System.out.println("服务器启动成功");


        while (true)
        {
            //接受此套接字的链接
            Socket socket = serverSocket.accept();
            //将客户添加到集合中
            socketList.add(socket);
            //在线人数
            System.out.println("在线人数:"+socketList.size());


            //创建线程对象 ,多少个客户端就多少个对象
            SeverThread severThread =new SeverThread(socket);
            severThread.start();


            //写数据
            DataOutputStream out =new DataOutputStream(socket.getOutputStream());
            out.writeUTF("服务器:"+sc.next());
        }




    }
}


//读取数据的线程  将某个客户端的消息发送给其他客户端


class SeverThread extends Thread
{
    private Socket socket;
    public SeverThread(Socket socket)
    {
        this.socket=socket;
    }
    @Override
    public void run() {


        //读取客户端数据
        try {
            while (true) {
                DataInputStream in = new DataInputStream(socket.getInputStream());
                String msg =in.readUTF();
                //System.out.println(in.readUTF());
                //遍历集合如果不是自己,就把消息发送
                for (Socket client : Sever.socketList)
                {
                    if(socket!=client )
                    {
                        DataOutputStream out = new DataOutputStream(client.getOutputStream());
                        out.writeUTF(msg);
                    }


                }


            }


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


    }
}

 

  • UDP协议开发

    • 无连接的,不可靠的协议
    • UDP通信思路:
      • A: 创建发送端 Socket 对象
      • B: 创建数据,并把数据打包
      • C: 调用 Socket 对象的发送方法发送数据包
      • D: 释放资源
    • 发送和接收都是使用 DatagramSocket
/*---------------接收-------------------*/

/**
* @Auther: etc
* @Date: 2019/8/5 15:20
* @Description:  接收包
*/
public class Receive
{
    public static void main(String[] args) throws IOException {


        DatagramSocket datagramSocket =
                new DatagramSocket(10010, InetAddress.getByName("localhost"));


        //存放数据的容器
        byte[] buf =new byte[1024];
        //接收到的数据包
        DatagramPacket packet =new DatagramPacket(buf,buf.length);


        datagramSocket.receive(packet);


        //输出数据包内容
        String str =new String (buf);
        System.out.println(str);

    }
}

/*--------------发送--------------------*/

/**
* @Auther: etc
* @Date: 2019/8/5 15:19
* @Description:
*/
public class Sent
{
    public static void main(String[] args) throws IOException {


        DatagramSocket send =
                new DatagramSocket(10086, InetAddress.getByName("localhost"));


        //要发送的内容
        String str="hello";


        //发送数据包
        DatagramPacket packet =new DatagramPacket(
                str.getBytes(),
                str.getBytes().length,
                InetAddress.getByName("localhost"),
                10010);
        send.send(packet);


    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值