【java查漏补缺】网络编程

文章介绍了网络编程的基础,即通过套接字进行通信,展示了从简单的客户端-服务器模型到能服务多个客户端的服务器模型的演变。在基本模型中,服务器仅能处理一个客户端,而通过多线程改造后,服务器能持续接受并处理多个客户端的请求。
摘要由CSDN通过智能技术生成

网络编程实际上就是通过套接字进行连接后进行通信,本质还是程序进行IO操作。

所谓套接字,实际上就是IP地址加上端口号的组合,通过套接字,可以连接到网络中某一台计算机的某一个进程。

下面就是客户端和服务器的简单例子,这个简单的例子中,服务器只能和一个客户端进行通信,并且当客户端连接结束后,客户端和服务器同时停止。

  • 简单的客户端服务器模型

我们首先来看一下服务器的代码,服务器的执行一共有五个步骤

  1. 实例化一个ServerSocket对象

  2. 使用Socket对象接收ServerSocket示例执行accept()方法的返回值,该方法会一直被被阻塞,建立socket连接

  3. 和客户端进行通信

  4. 关闭Socket连接

  5. 关闭ServerSocket连接

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

public class ServerDemo {
    public static final int PORT = 8005;

    public static void main(String[] args) throws IOException {
        ServerSocket s = new ServerSocket(PORT);
        System.out.println("Started:" + s);
        try{
            Socket socket = s.accept();
            try{
                System.out.println("Connection accepted: " + socket);
                BufferedReader in =
                        new BufferedReader(
                                new InputStreamReader(socket.getInputStream()));
                PrintWriter out =
                        new PrintWriter(
                                new BufferedWriter(
                                        new OutputStreamWriter(socket.getOutputStream())));
                while(true){
                    String str = in.readLine();
                    System.out.println("Echoing: " + str);
                    if(str.equals("END")) break;
                    out.println("Receiving: " + str);
                    out.flush();
                }
            } finally {
                System.out.println("closing...");
                socket.close();
            }

        } finally {
            s.close();
        }
    }

}

客户端连接相对来说比较简单,连接步骤有三个

  1. 建立Socket连接,其中需要传入两个参数,分别是服务器的IP地址和端口号

  2. 和服务器进行通信

  3. 关闭Socket连接

 

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class ClientDemo {

    public static void main(String[] args) throws IOException {
        InetAddress addr = InetAddress.getByName("127.0.0.1");
        System.out.println("addr=" + addr);
        Socket socket = new Socket(addr, ServerDemo.PORT);
        try{
            System.out.println("socket=" + socket);
            BufferedReader in =
                    new BufferedReader(new InputStreamReader(System.in));
            BufferedReader serverIn =
                    new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out =
                    new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
            while(true){
                String line = in.readLine();
                out.println(line);
                out.flush();
                String serverInfo = serverIn.readLine();
                if(serverInfo != null){
                    System.out.println(serverInfo);
                }
                if(line.equals("END")) break;
            }
        } finally {
            System.out.println("closing...");
            socket.close();
        }
    }

}

上述例子中ServerDemo是服务器类,ClientDemo是客户端类,连接建立后,客户端可以给服务器发送消息,知道服务器收到"END"字符串的时候停止服务。

 

  • 可以服务多个客户端的服务器模型

上述的服务器模型只能对一个客户端进行连接,当连接断开之后,服务器程序也会停止。当然,一个好用的服务器需要随时随刻都能服务尽可能多的客户端,我们只需要对上述代码稍加修改,就能实现一个功能稍微复杂的服务器模型。

可以服务多个客户端的服务器模型的基本逻辑是,持续监听accept()方法是否有返回,一旦有返回,就接收其返回的Socket对象,并且新建立一个线程执行服务器逻辑,然后再持续监听accept()方法,重复上述步骤。

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

public class MultiServerDemo {

    public static final int PORT = 8005;

    public static void main(String[] args) throws IOException {
        ServerSocket s = new ServerSocket(PORT);
        System.out.println("Server Started");
        try {
            while(true){
                Socket socket = s.accept();
                try {
                    new ServerOneDemo(socket);
                } catch (IOException e) {
                    socket.close();
                }
            }
        } finally {
            s.close();
        }
    }
}

class ServerOneDemo extends Thread{
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    public ServerOneDemo(Socket s) throws IOException{
        socket = s;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
        // 启动线程
        start();
    }
    public void run(){
        try {
            while(true){
                String str = in.readLine();
                System.out.println("Echoing: " + str);
                if(str.equals("END")) break;
                out.println("Receiving: " + str);
                out.flush();
            }
            System.out.println("closing...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上述代码分为两个类来编写,其中MultiServerDemo类负责监控accpet()方法的返回情况,一点有返回值就会实例化一个ServerOneDemo。ServerOneDemo类继承了Thread,实现了run()方法,在构造函数中接收一个Socket对象作为参数,并且执行start()方法自动开启线程。执行代码,可以发现,只要我们不结束程序,那么就可以一直和客户端建立连接并接收消息。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值