Day23、网络编程

1、Socket简介

1.1、什么是Socket

1)通信链路的端点就被称为“套接字”(英文名Socket)

2)是提供给应用程序的接口

3)Socket的底层机制复杂,Java平台提供了一些简单的API,可以更简单有效的使用Socket开发而无需了解底层机制

1.2、基于TCP协议的Socket编程

1)基于TCP协议的Socket网络通信

        用来实现双向安全连接网络通信

2)Socket通信模型

        进行网络通信时,Socket需要借助数据流来完成数据的传递工作

 

 3)Socket网络编程一般可以分成如下步骤进行

 

 1.3、Socket中实现对象的传递

1)传递对象信息

ObjectOutputStream  oos = new  ObjectOutputStream(…);
oos.writeObject(…);

ObjectInputStream  ois = new  ObjectInputStream(…);
Object = ois.readObject();

 

1.4、基于UDP协议的Socket编程

1)

 

 2)基于UDP协议的Socket网络编程步骤

 

2、模拟用户登录的功能

需求说明

模拟用户登录的功能

实现客户发送登录用户信息,服务器端显示登录信并响应给客户端登录成功

1)客户端实现步骤如下:
          (1)建立连接,连接指向服务器及端口
          (2)打开Socket关联的输入/输出流
          (3)向输出流中写入信息
         (4)从输入流中读取响应信息
         (5)关闭所有的数据流和Socket



import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class LoginClient {
    /*
     * 示例01:模拟用户登录的功能,实现客户端发送用户登录信息,服务器端显示登录信息并响应给客户端登录成功
     *
     * 客户端实现步骤如下:
     * 	(1)建立连接,连接指向服务器及端口
     * 	(2)打开Socket关联的输入/输出流
     *	(3)向输出流中写入信息
     *	(4)从输入流中读取响应信息
     *	 (5)关闭所有的数据流和Socket
     */
    public static void main(String[] args) {
        Socket socket=null;
        OutputStream os=null;
        InputStream is=null;
        BufferedReader br=null;

        try {
            //建立客户端Socket连接,指定服务器的位置为本机以及端口为8800
            socket=new Socket("localhost",8800);
            //打开输出流
            os=socket.getOutputStream();
            //接收服务器端的响应,即从输入流中读取信息
            String info="用户名:Tom;用户密码:123456";
            /*
            byte[] byte=info.getBytes();
            os.write(byte);
             */
            os.write(info.getBytes());
            //关闭通道
            socket.shutdownOutput();

            //接收服务器端的响应,即从输入流中读取信息
            String reply;
            is=socket.getInputStream();
            br=new BufferedReader(new InputStreamReader(is));
            while((reply=br.readLine())!=null){
                System.out.println("我是客户端,服务器的响应为:"+reply);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                br.close();
                is.close();
                os.close();
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

 

2)服务器端实现步骤如下:
              (1)建立连接,监听端口
              (2)使用accept()方法等待客户端发起通信
              (3)打开Socket关联的输入/输出流
              (4)向输出流中写入信息
              (5)从输入流中读取响应信息
              (6)关闭所有的数据流和Socket



import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;


public class LoginServer {
    public static void main(String[] args) {
        /*
         * 示例01:模拟用户登录的功能,实现客户端发送用户登录信息,服务器端显示登录信息并响应给客户端登录成功
         *
         * 服务器端实现步骤如下:
         * 	(1)建立连接,监听端口
         * 	(2)使用accept()方法等待客户端发起通信
         * 	(3)打开Socket关联的输入/输出流
         * 	(4)向输出流中写入信息
         * 	(5)从输入流中读取响应信息
         * 	(6)关闭所有的数据流和Socket
         */
        ServerSocket serverSocket=null;
        Socket socket=null;
        InputStream is =null;
        BufferedReader br =null;
        OutputStream os=null;

        try {
            //建立一个服务器Socket(ServerSocket),指定端口8800并开始监听
            serverSocket=new ServerSocket(8800);
            //使用accept()方法等待客户端发起通信
            socket=serverSocket.accept();
            //打开输入流
            is=socket.getInputStream();
            //获取客户端信息,即从输入流读取信息
            br=new BufferedReader(new InputStreamReader(is));
            String info;
            while((info=br.readLine())!=null){
                System.out.println("我是服务器,客户登录信息为:"+info);
                //给客户端一个响应,即向输出流中写入信息
            }
            os=socket.getOutputStream();
            String reply="欢迎你,登录成功";
            os.write(reply.getBytes());
            /*
            byte[] byte=reply.getBytes();
            os.write(byte);
             */
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //关闭资源
            try {
                os.close();
                br.close();
                is.close();
                socket.close();
                serverSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3、多客户端用户登录

需求说明

升级前一个上机内容,实现多客户端用户登录

分析

创建服务器端线程类,run()方法中实现对一个请求的响应处理

修改服务器端代码,实现循环监听状态

服务器端每监听到一个请求,创建一个处理线程

 

1)Student类


import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
        super();
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }

}

 

2)ServerThread类



import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ServerThread extends Thread {
    //声明一个Socket类型的属性
    private Socket socket;

    public ServerThread(Socket socket) {
        super();
        this.socket = socket;
    }


    @Override
    public void run() {

        InputStream is =null;
        ObjectInputStream ois =null;
        OutputStream os =null;
        try {
            //通过返回的Socket对象调用方法获取一个输入流来读取客户端发送过来的消息
            is =socket.getInputStream();
            ois = new ObjectInputStream(is);
            Object object = ois.readObject();
            Student student = (Student)object;
            System.out.println("我这边是服务器:客户端发送给我的数据是:"+student.getName()+","+student.getAge());
            socket.shutdownInput();

            //服务器接收客户端消息后,需要给客户端一个响应信息
            os =socket.getOutputStream();
            String result = "获取的对象姓名和年龄正确";
            byte[] bytes = result.getBytes();
            os.write(bytes);
            System.out.println("给客户端的响应信息发送成功");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                os.close();
                ois.close();
                is.close();
                socket.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
        }



    }

}

 

3)Server类



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

public class Server {

    /*
     * 多个客户端向服务器发送请求,服务器怎么办???
     *
     *
     * 客户端跟之前客户端做的事情没有任何改变
     * 		客户端通过输出流发送请求信息
     * 		客户端通过输入流获取服务器端的响应信息
     * 服务器端做的事情跟之前服务器端做的事情不一样
     * 		服务器端循环去侦听客户端的请求,侦听到一个请求就会获取一个Socket类对象,将这个Socket类对象作为参数传递给服务器线程类的有参构造方法里去
     * 服务器线程类通过获取到的Socket类对象去执行原来服务器所做的事情
     * 		通过输入流获取客户端的请求信息
     * 		通过输出流发送响应信息给客户端
     *
     */
    public static void main(String[] args) {

        //创建ServerSocket类对象
        ServerSocket ss =null;
        Socket socket =null;
        try {
            ss = new ServerSocket(10088);
            while(true){
                socket =ss.accept();
                //将获取到的socket对象传递到线程类中
                ServerThread st = new ServerThread(socket);
                st.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

4)Client1类



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client1 {

    public static void main(String[] args) {

        //创建通信链路的端点客户端套接字
        Socket socket  = null;
        OutputStream os = null;
        ObjectOutputStream oos =null;
        InputStream is =null;
        BufferedReader br =null;
        try {
            socket  = new Socket("127.0.0.1", 10088);
            //获取输出流将数据发送出去
            os =socket.getOutputStream();
            //准备Student类对象
            Student stu = new Student("张三",19);

            oos = new ObjectOutputStream(os);
            oos.writeObject(stu);

            System.out.println("我是客户端,我将数据发送完毕");
            //关闭通道
            socket.shutdownOutput();

            //客户端需要通过输入流读取服务器端发送过来的消息
            is =socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String result =br.readLine();
            System.out.println("我是客户端,接收到的服务器端响应信息为:"+result);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                is.close();
                oos.close();
                os.close();
			socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

5)Client2类


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client2 {

    public static void main(String[] args) {

        //创建通信链路的端点客户端套接字
        Socket socket  = null;//创建一个未连接的套接字
        OutputStream os = null;
        ObjectOutputStream oos =null;
        InputStream is =null;
        BufferedReader br =null;
        try {
            socket  = new Socket("127.0.0.1", 10088);
            //获取输出流将数据发送出去
            os =socket.getOutputStream();
            //准备Student类对象
            Student stu = new Student("李四",22);

            oos = new ObjectOutputStream(os);
            oos.writeObject(stu);

            System.out.println("我是客户端,我将数据发送完毕");
            //关闭通道
            socket.shutdownOutput();

            //客户端需要通过输入流读取服务器端发送过来的消息
            is =socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String result =br.readLine();
            System.out.println("我是客户端,接收到的服务器端响应信息为:"+result);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                is.close();
                oos.close();
                os.close();
				socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

6)Client3类



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client3 {

    public static void main(String[] args) {

        //创建通信链路的端点客户端套接字
        Socket socket  = null;
        OutputStream os = null;
        ObjectOutputStream oos =null;
        InputStream is =null;
        BufferedReader br =null;
        try {
            socket  = new Socket("127.0.0.1", 10088);
            //获取输出流将数据发送出去
            os =socket.getOutputStream();
            //准备Student类对象
            Student stu = new Student("如花",16);

            oos = new ObjectOutputStream(os);
            oos.writeObject(stu);

            System.out.println("我是客户端,我将数据发送完毕");
            //关闭通道
            socket.shutdownOutput();

            //客户端需要通过输入流读取服务器端发送过来的消息
            is =socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String result =br.readLine();
            System.out.println("我是客户端,接收到的服务器端响应信息为:"+result);

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                is.close();
                oos.close();
                os.close();
				socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

4、客户咨询问题

需求说明

实现客户咨询问题,客服人员答复问题

分析

咨询时,客户是发送方,客服人员是接收方

答复时,客服人员是发送方,客户是接收方,实现思路和咨询时相同

1)LoginServer类



import java.io.IOException;
import java.net.*;

public class LoginClient {
    public static void main(String[] args) {
        String info="您好,我想咨询一些问题!";
        byte[] infos=info.getBytes();
        DatagramSocket socket=null;
        try {
            InetAddress ia=InetAddress.getByName("localhost");
                DatagramPacket dp = new DatagramPacket(infos, infos.length, ia, 5000);
                socket = new DatagramSocket();
                socket.send(dp);
                byte[] replya = new byte[100];
                DatagramPacket dpt = new DatagramPacket(replya, replya.length);
                socket.receive(dpt);
                String reply = new String(dpt.getData(), 0, dpt.getData().length);
                System.out.println("服务器回应:" + reply);

        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        } catch (SocketException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            socket.close();
        }
    }
}

 

2)LoginClient类



import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;

public class LoginServer {
    public static void main(String[] args) {
        byte[] infos=new byte[100];
        DatagramPacket dp=new DatagramPacket(infos,infos.length);
        DatagramSocket socket=null;
        try {
            socket=new DatagramSocket(5000);
            socket.receive(dp);
            String reply = "您好,我在,请说!";

                String info=new String(dp.getData(),0,dp.getData().length);
                System.out.println("客户端说:"+info);

                SocketAddress sa = dp.getSocketAddress();
                DatagramPacket dpt = new DatagramPacket(reply.getBytes(), 0, reply.getBytes().length, sa);
                socket.send(dpt);

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值