网络编程java

网络编程基本概念

  • TCP: 传输控制协议,采用三方握手的方式,保证准确的连接操作
  • UDP: 数据报协议,发送数据报【不安全、不可靠】
  • 数据帧: 协议类型、源IP、目标IP、源端口、目标端口、帧序号、帧数据

网络编程TCP协议

  • TCP是一个可靠的协议,面向连接的协议
  • 实现TCP协议,需要编写服务器端和客户端,Java API为我们提供了java.net包,为实现网络应用程序提供类
  • ServerSocket 此类实现服务器套接字
  • Socket 此类实现客户端套接字 【是网络驱动层提供给应用程序编程的接口和一种机制】

数据发送过程【IO流】

在这里插入图片描述

实现服务器端与客户端程序

//服务器端
public class ServerSocket extends Object
    //此类实现服务器套接字。服务器套接字等待请求通过网路传入。它基于该请求执行某些操作,然后可能向请求者返回结果
ServerSocket(int port)
    //创建绑定到特定端口的服务器套接字
void setTimeout(int timeout)
    //通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位
InetAddress getInetAddress() 
    //返回服务器套接字的本地地址
Socket accept()
    //侦听并接受到此套接字的连接
    
//客户端
public class Socket extends Object
    // 此类实现客户端套接字。套接字是两台机器间通信的端点
Socket(String host,int port)
    //创建一个流套接字并将其连接到指定主机上的指定端口号
InputStream getInputStream()
    //返回此套接字的输入流
OutputStream getOutputStream()
    //返回此套接字的输出流
void setSoTimeout(int timeout)
    //启用/禁用带有指定超时值的SO_TIMEOUT,以毫秒为单位
    

TCP实现ECHO程序

  • Echo,应答。
    • 客户端向服务器发送一个字符串,服务器不做任何处理,直接把字符串返回给客户端,Echo程序是最为基本的客户/服务器程序
public class EchoServerDemo {
    public static void main(String[] args) {
        //创建一个服务器端的Socket(1024-65535)
        try {
            ServerSocket server = new ServerSocket(6666);
            System.out.println("服务器已启动,正在等待客户端的连接。。。");

            //等待客户端的连接,造成阻塞。如果有客户端连接成功,立即返回一个Socket对象
            Socket socket = server.accept();
            System.out.println("客户端连接成功"+server.getInetAddress().getHostAddress());

            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //通过输入流读取网络数据  [没有数据造成阻塞]
            String info = br.readLine();
            System.out.println(info);
            //获取输出流,向客户端返回消息
            PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
            ps.println("echo:"+info);
            ps.flush();
            //关闭
            ps.close();
            br.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
public class EchoClientDemo {
    public static void main(String[] args) {
        //创建一个Socket对象,指定要连接的服务器
        try {
            Socket socket = new Socket("localhost",6666);
            //获取socket的输入输出流
            PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            ps.println("hello,my name is Bin");
            ps.flush();

            //读取服务器返回的数据
            String info = br.readLine();
            System.out.println(info);
            ps.close();
            br.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

服务器与多客户端通信

  • 服务器多线程
public class MutilServerDemo {
    public static void main(String[] args) {

        //线程池
        ExecutorService es = Executors.newFixedThreadPool(3);
        try {
            ServerSocket server = new ServerSocket(7777);
            System.out.println("服务器已启动,等待连接。。。");
            while (true){
                Socket s = server.accept();
                System.out.println(s.getInetAddress().getHostAddress());
                es.execute(new UserThread(s));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }
}

/**
 * 用来处理客户端请求的线程
 */
class UserThread implements Runnable {
    private Socket s;

    public UserThread(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));
            String info = br.readLine();
            System.out.println(info);
            ps.println("echo:"+info);
            ps.flush();
            ps.close();
            br.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
public class MutilClientDemo {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        //创建一个Socket对象,指定要连接的服务器
        try {
            Socket socket = new Socket("localhost",7777);
            //获取socket的输入输出流
            PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            System.out.println("请输入:");
            String info = input.nextLine();
            ps.println(info);
            ps.flush();

            //读取服务器返回的数据
            info = br.readLine();
            System.out.println(info);
            ps.close();
            br.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

多客户端之间的通信

public class Message implements Serializable {
    private String from;  //发送者
    private String to;   //接收者
    private int type;      //消息类型
    private String info;   //消息

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public Message(String from, String to, int type, String info) {
        this.from = from;
        this.to = to;
        this.type = type;
        this.info = info;
    }

    public Message() {
    }

    @Override
    public String toString() {
        return "Message{" +
                "from='" + from + '\'' +
                ", to='" + to + '\'' +
                ", type=" + type +
                ", info='" + info + '\'' +
                '}';
    }
}
public final class MessageType {
    public static final int TYPE_LOGIN = 0x1;  //登录消息类型
    public static final int TYPE_SEND = 0x2;   //发送消息的类型
}
/**
 * 服务器端
 */

public class Server {
    public static void main(String[] args) {
        //保存客户端处理的数据
        Vector<UserThread> vector = new Vector<>();
        ExecutorService es = Executors.newFixedThreadPool(5);
        //创建服务器端的Socket
        try {
            ServerSocket server = new ServerSocket(9999);
            System.out.println("服务器已启动。正在等待连接....");
            while (true){
                Socket socket = server.accept();
                UserThread user = new UserThread(socket,vector);
                es.execute(user);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * 客户端处理线程
 */
class UserThread implements Runnable{
    private String name;   //客户端的用户名称(唯一)
    private Socket socket;
    private Vector<UserThread> vector;  //客户端处理线程集合
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private boolean flag = true;

    public UserThread(Socket socket,Vector<UserThread> vector){
        this.socket = socket;
        this.vector = vector;
        vector.add(this);
    }


    @Override
    public void run() {
        try {
            System.out.println("客户端"+socket.getInetAddress().getHostAddress()+"已连接");
            ois = new ObjectInputStream(socket.getInputStream());
            oos = new ObjectOutputStream(socket.getOutputStream());

            while(flag){
                //读取消息对象
                Message msg = (Message) ois.readObject();
                int type = msg.getType();
                switch (type){
                    case MessageType.TYPE_LOGIN:
                        name = msg.getFrom();
                        msg.setInfo("欢迎你:");
                        oos.writeObject(msg);
                        break;
                    case MessageType.TYPE_SEND:
                        String to = msg.getTo();
                        UserThread ut;
                        int size = vector.size();
                        for (int i = 0; i < size; i++) {
                            ut = vector.get(i);
                            if(to.equals(ut.name) && ut != this){
                                ut.oos.writeObject(msg);
                                break;
                            }
                        }
                        break;
                }
            }
            ois.close();
            oos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        ExecutorService es = Executors.newSingleThreadExecutor();
        try {
            Socket socket = new Socket("localhost",9999);
            System.out.println("服务器连接成功");
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            //向服务器发送登录信息
            System.out.println("请输入名称:");
            String name = input.nextLine();
            Message msg = new Message(name,null,MessageType.TYPE_LOGIN,null);
            oos.writeObject(msg);
            msg = (Message) ois.readObject();
            System.out.println(msg.getInfo()+msg.getFrom());
            //启动读取消息的线程
            es.execute(new ReadInfoThread(ois));

            //使用主线程来实现发送消息
            boolean flag = true;
            while(flag){
                msg = new Message();
                System.out.println("TO:");
                msg.setTo(input.nextLine());
                msg.setFrom(name);
                msg.setType(MessageType.TYPE_SEND);
                System.out.println("Info:");
                msg.setInfo(input.nextLine());
                oos.writeObject(msg);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

class ReadInfoThread implements Runnable{
    private ObjectInputStream in;
    private boolean flag = true;

    public void setFlag(boolean flag){
        this.flag = flag;
    }
    public ReadInfoThread(ObjectInputStream in) {
        this.in = in;
    }


    @Override
    public void run() {
        try{
            while(flag){
                Message message = (Message) in.readObject();
                System.out.println("["+message.getFrom()+"]对我说:"+message.getInfo());
            }
            if(in != null){
                in.close();
            }
            }catch(IOException|ClassNotFoundException e){
                e.printStackTrace();
        }
    }
}

网络编程UDP协议

  • 无连接协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络中以任何可能的路径传往目的地,能否到达目的地、到达目的地的时间以及内容的正确性不能被保证,每个传输的数据报必须限定在64KB之内
DatagramPacket   //表示数据报包
DatagramSocket   //用来发送和接收数据报包的套接字
public class UDPClientDemo {
    public static void main(String[] args) {

        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length);

        try {
            DatagramSocket socket = new DatagramSocket(8020);
            System.out.println("正在接收数据...");
            socket.receive(dp);
            String s = new String(dp.getData(),0,dp.getLength());
            System.out.println(s);
            socket.close();

        } catch (SocketException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
public class UDPServerDemo {
    public static void main(String[] args) {

        String info = "good good 学习,天天 up";
        byte[] bytes = info.getBytes();

        try {

            DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length,
                    InetAddress.getByName("127.0.0.1"),8020);
            //本程序端口
            DatagramSocket socket = new DatagramSocket(9022);
            socket.send(dp);
            socket.close();

        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        } catch (SocketException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

URL

  • 统一资源定位符
public class URLDemo {
    public static void main(String[] args) {

        try {

            URL url = new URL("https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF");

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("E:\\baidu.png"));
            byte[] bytes = new byte[1024];
            int len = -1;
            while((len=in.read(bytes)) != -1){
                out.write(bytes,0,len);
                out.flush();
            }
            in.close();
            out.close();
            System.out.println("下载成功");

        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值