Java

java学习笔记#8-Java Socket

2017-08-30  本文已影响0人  edwin1993

网络基础

通信必备条件.png

IP+端口号 组成了Socket。Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。

JAVA中的网络支持
针对网络通信的不同层次,java提供的网络功能分为四大类

InetAddress类

无构造方法,无法通过new的方法创造对象。有很多静态方法,可以返回该类。

public void useInetAddress(){

        try {
            //        获取本机的InetAddress
            InetAddress inetAddress = InetAddress.getLocalHost();
            System.out.println("计算机名" + inetAddress.getHostName());
            System.out.println("计算机IP" + inetAddress.getHostAddress());
            System.out.println(inetAddress);

//            其它获取inetAddress的方式
//            InetAddress inetAddress2 = InetAddress.getByName("Edwin");
//            InetAddress inetAddress3 = InetAddress.getByName("1.1.1.10");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }

URL类

public void useURL(){
        try {
//            创建URL实例
            URL immoc = new URL("http://www.imooc.com");
            URL url = new URL(immoc,"/index.html?username=tom#test");

            System.out.println("协议:"+ url.getProtocol());
            System.out.println("Host:"+ url.getHost());
//            如果为指定端口号,则为-1
            System.out.println("Port:" + url.getPort() );
            System.out.println("filePath:" + url.getPath());
            System.out.println("fileName:" + url.getFile());
            System.out.println("相对路径:"+ url.getRef());
            System.out.println("查询字符串:"+ url.getQuery());




            URL baidu = new URL("http://www.baidu.com");
//            通过URL对象的openStream方法可以获取指定资源的输入流
            InputStream inputStream = baidu.openStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
//            添加缓冲 提高效率
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String data = bufferedReader.readLine();
            while (data!=null){
                System.out.println(data);
                data = bufferedReader.readLine();
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();

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

Socket-TCP编程简介

Socket通信模型.png

实现步骤:
创建serversocket 和socket
打开连接到socket的输入/输出流
按照协议读写
关闭输入输出流

public class ServerModel {
    public static void main(String args[]){
        try {
//       创建服务器端的socket,绑定指定的端口并监听
            ServerSocket serverSocket = new ServerSocket(8888);
//            调用accept监听
            System.out.println("等待客户端链接");
            Socket socket = serverSocket.accept();
//            获取客户端的信息
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferedReader = new BufferedReader(isr);
            String info = null;
            while ((info = bufferedReader.readLine())!=null){
                System.out.println("client info : " + info);
            }
            socket.shutdownInput();

            OutputStream outputStream = socket.getOutputStream();
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.write("welcome");
            printWriter.flush();

//           关闭资源
            printWriter.close();
            outputStream.close();

            bufferedReader.close();
            isr.close();
            is.close();
            socket.close();
            serverSocket.close();

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

public class ClientModel {
    public static void main(String args[]){
//        创建客户端的socket,指定服务器端的地址和端口
        try {
            Socket socket = new Socket("localHost",8888);
//            获取输出流发送登陆信息
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write("userName:edwin;key:123");
            pw.flush();

            socket.shutdownOutput();
//            获取输入流来获取服务器端的响应
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String info = null;
            while ((info = bufferedReader.readLine())!= null){
                System.out.println("server said:"+info);
            }
//            关闭资源
            bufferedReader.close();
            inputStream.close();

            pw.close();
            os.close();
            socket.close();

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


运行结果.png 运行结果.png

为上面所演示的程序添加多线程来实现多客户端的功能
继承线程类

public class ServerThread extends Thread {

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

//    线程执行的操作,响应客户端的请求
    public void run(){
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader bufferedReader = null;
        OutputStream outputStream = null;
        PrintWriter printWriter = null;
        try {
 //            获取客户端的信息
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            bufferedReader = new BufferedReader(isr);
            String info = null;
            while ((info = bufferedReader.readLine())!=null){
                System.out.println("client info : " + info);
            }
            socket.shutdownInput();
            outputStream = socket.getOutputStream();
            printWriter = new PrintWriter(outputStream);
            printWriter.write("welcome");
            printWriter.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //           关闭资源
            try{
                printWriter.close();
                outputStream.close();
                bufferedReader.close();
                isr.close();
                is.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

在服务器端启动循环监听

Socket socket = null;
            int count = 0;
//            循环监听
            while (true){
                socket = serverSocket.accept();
//                创建线程
                ServerThread serverThread = new ServerThread(socket);
                serverThread.run();
                System.out.println(++count);
            }
运行结果.png

Socket-UDP编程简介

UDP无连接无序,数据封装为数据报的形式(datagram)

public class UDPServer {
    public static void main(String args[]){
        try {
//            创建服务器端的DatagramSocket,指定端口
            DatagramSocket socket = new DatagramSocket(8800);
//            创建数据报文,由于接受服务端的数据
            byte[] data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data,data.length);
//            接收数据
            System.out.println("服务器端启动...");
            socket.receive(packet);//此方法在接收到数据之前会一直阻塞
//            读取数据
            System.out.println("从客户端得到的数据为:"+ new String(data));
//            向客户端发送响应
//            定义客户端的地址,端口等
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            byte[] reMessage = "welcome".getBytes();
//            创建数据报
            DatagramPacket rePacket = new DatagramPacket(reMessage,reMessage.length,address,port);
//            响应
            socket.send(rePacket);
            socket.close();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


public class UDPClient {
    public static void main(String args[]){
        try {
//            定义服务器地址
            InetAddress address =InetAddress.getByName("localHost");
            int port = 8800;
            byte[] data = "此为服务端数据内容".getBytes();
//            创建数据报
            DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
//            创建socket
            DatagramSocket socket = new DatagramSocket();
//            发送
            socket.send(packet);
//            接收响应
            byte[] reMessage = new byte[1024];
            DatagramPacket repacket = new DatagramPacket(reMessage,reMessage.length);
            socket.receive(repacket);
            System.out.println(new String(reMessage));
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
运行结果.png

补充内容

在TCP的示例中使用了多线程来完成持续监听来模拟多个客户端的访问,我们可以通过设计线程的优先级来调整程序的运行情况

...
serverThread.setPriority(4);//范围[1,10],默认:5
...

输出流关闭的过程中会一起关闭socket,所以不单独进行关闭。传输可以以对象的形式进行,只需要使用ObjectOutputStream。

上一篇 下一篇

猜你喜欢

热点阅读