Java_网络编程

网络通信的关键三要素

IP、端口号、协议

IP地址

IP地址(Internet Protocol):全程“互联网协议地址”,是分配给上网设备的唯一标志。

IP地址有两种形式:IPv4、IPv6

在这里插入图片描述

在这里插入图片描述

InetAddress

代表IP地址

InetAddress 的常用方法如下

名称说明
public static InetAdress getLocalHost()获取本机IP,会以一个inetAddress 的对象返回
public static InetAddress getByName(String host)根据ip地址或者域名,返回一个inetAddress对象
public String getHostName()获取该IP地址对象对应的主机名。
public String getHostAddress()获取该IP地址对象中的ip地址信息
public boolean isReachable(int timeout)在指定毫秒内,判断主机与该ip对应主机是否能够联通
import java.net.InetAddress;
import java.sql.SQLOutput;

public class InetAddresstest {


    public static void main (String[] args )throws Exception
    {
        //1、获取本机IP地址对象

        InetAddress ip1 = InetAddress.getLocalHost();
        System.out.println(ip1.getHostName());
        System.out.println(ip1.getHostAddress());

        //2、获取指定IP或者域名的IP地址对象
        InetAddress ip2=InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostName());
        System.out.println(ip2.getHostAddress());

        System.out.println(ip2.isReachable(6000));

    }


}

端口号

标记正在设备上运行的应用程序的,被规定为一个16位的二进制,范围是0~65535

分类

周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)

注册端口:1024~49151,分配给用户进程或某些应用程序。

动态端口:49151到65535,之所以被称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则会出错。

通信协议

网络上通信设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议。

开放式互联网络互联标准:OSI 网络参考模型

OSI网络参考模型:全球网络互联标准
TCP/IP网络模型:事实上的国际标准
在这里插入图片描述

传输层的两个通信协议

UDP(User Datagram Protocol):用户数据报协议;
TCP(Transmission Control Protocol) :传输控制协议

UDP

特点:无连接、不可靠通信

不事先建立连接,数据按照包发,一包数据含:自己的IP、程序端口、目的IP、程序端口和数据(限制在64KB内)
发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,是不可靠的。

TCP

特点:面向连接、可靠通信。
TCP的最终目的:要保证在不可靠的信道上实现可靠传输。
TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接。

在这里插入图片描述

在这里插入图片描述

UDP通信

特点:无连接、不可靠通信
不事先建立连接;发送端每次要把发送的数据(限制在64KB内)、接收端IP、等信息封装成一个数据包,发不出去就算了。
Java提供了一个Java.net.DatagramSocket类来实现UDP通信。

在这里插入图片描述

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.sql.SQLOutput;

public class Server {


    public static void main(String[] args) throws Exception
    {
        //1、创建一个服务对象(创建一个接韭菜的人)注册端口


        DatagramSocket socket =new DatagramSocket(
                6666);

        //2、创建一个数据包对象,用于接受数据的(创建一个韭菜盘子)
        byte[] buffer = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            //3、开始正式使用数据包来接受客户端发来的数据
            socket.receive(packet);

            //4、从字节数组中,把接收到的数据直接打印出来
            //接受多少就到处多少
            //获取本次数据包接受了多少数据。

            int len = packet.getLength();

            String rs= new String(buffer,0,len);

            System.out.println(rs);
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(packet.getPort());
            System.out.println("----------------");
        }
    }
}


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception{
        //1、创建客户端对象
        DatagramSocket socket = new DatagramSocket();


        //2、创建数据包对象封装要发出去的数据(创建一个韭菜盒子)
        //public DatagramPacket(byte buf[],int length,InetAddress address,int port)
         //InetAddress address,int port)
        //参数1:封装要发出去的数据。
        //参数2:发出去的数据大小(字节个数)
        //参数3:服务器额的IP地址
        //参数4:服务程序的端口

        Scanner sc= new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg= sc.nextLine();
            if("exit".equals(msg)) {
                System.out.println("欢迎下次光临!推出成功!");
                socket.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);

            //3、正式发送这个数据包的数据出去了

            socket.send(packet);

        }


    }
}



TCP通信

特点:面向连接、可靠通信

通信方面事先会采用”方式建立可靠连接“,实现端到端的通信;底层能保证数据成功传给服务器

java提供了一个Java.net.Socket类来实现TCP通信。


import java.io.DataInputStream;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLOutput;

public class Server {


    public static void main(String[] args) throws Exception
    {
        //1、创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        //2、从serverSocket对象,调用accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept();

        //3、从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        //4、把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        //5、使用数据输入流读取客户端发过来的消息
         String rs=dis.readUTF();

         System.out.println(rs);
         //其实我们也可以获取客户端的IP地址
        System.out.println(socket.getRemoteSocketAddress());

        dis.close();
        socket.close();

    }
}

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

public class Client {

    public static void main(String[] args) throws Exception{

       //1、创建Socket对象,并同时请求与服务端程序的连接
        Socket socket= new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序。
        OutputStream os= socket.getOutputStream();


        //3、把低级字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);


        //4.开始写数据出去了
        dos.writeUTF("在一起号码!");

        dos.close();
        socket.close();

    }
}



下面是一个简单的Java程序,用于实现多个客户端同时通信:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class MultiClientServer {

    private List<Socket> clients = new ArrayList<>();

    public static void main(String[] args) {
        MultiClientServer server = new MultiClientServer();
        server.start();
    }

    public void start() {
        try {
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("Server started");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                clients.add(clientSocket);

                ClientHandler clientHandler = new ClientHandler(clientSocket);
                Thread clientThread = new Thread(clientHandler);
                clientThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class ClientHandler implements Runnable {

        private Socket clientSocket;
        private BufferedReader reader;
        private PrintWriter writer;

        public ClientHandler(Socket clientSocket) {
            this.clientSocket = clientSocket;
            try {
                reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                writer = new PrintWriter(clientSocket.getOutputStream(), true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            try {
                String message;
                while ((message = reader.readLine()) != null) {
                    System.out.println("Received message: " + message);

                    // 向所有客户端发送消息
                    for (Socket client : clients) {
                        PrintWriter clientWriter = new PrintWriter(client.getOutputStream(), true);
                        clientWriter.println(message);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

这个程序创建了一个服务器端,可以同时处理多个客户端的连接。当一个客户端发送消息时,服务器会将该消息转发给所有连接的客户端。

运行这个程序后,可以使用多个客户端程序连接到服务器,并进行通信。每个客户端发送的消息都会被服务器广播给所有连接的客户端。

注意:这个程序是一个简单的示例,没有处理异常情况和并发安全性。在实际使用中,应该对异常进行处理并确保多个线程之间的安全访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值