Socket编程——实现单点和多点网络连接

Socket

概念

Socket就是JAVA提供给网络编程的一个接口,通过Socket可以让服务器和客户端建立通道,通过套接字Socket获取网络连接中的各种信息,从而实现网络编程

用到的包名是 java.net.Socket 和 java.net.ServerSocket

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力 ——from 百度百科

连接步骤

架设服务器

  1. 创建一个ServerSocket对象,并且赋予他占用的端口号

ServerSocket server = new ServerSocket(6666);

  1. 使用ServerSocket对象的accept()方法等待一个Socket对象连接进来,这个过程如果一直没有客户端连接,程序将会一直在这个位置等待。把接收到的对象用一个Socket保存起来(下一个步骤会和架设客户端的步骤3同步运行)

Socket s = server.accept();

  1. 创建一个输入流一个输入流。

BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));

  1. 输入输出信息并且关闭流。(输出信息后需要刷新)

String s = br.readLine();
System.out.println(s);
ps.println(“echo:”+s);
ps.flush();
ps.close();
br.close();

架设客户端

  1. 创建一个Socket对象,赋予主机地址和端口号(自己Debug一下可以发现,代码执行完这一步服务器端就已经接收到连接了)System.out.println(s.getInetAddress().getHostAddress());用于测试接收客户端ip地址

Socket s = new Socket(“localhost”,6666);

  1. 创建一个输入流一个输入流。

PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

  1. 输入输出信息并且关闭流。(输出信息后需要刷新)

ps.flush();
System.out.println(“请输入姓名:”);
sc.nextLine();
String s1 = br.readLine();
System.out.println(s1);
ps.close();
br.close();

到此为止实现了服务器和客户端的单点连接,容易发现服务器代码中现在只支持和单个客户端连接,并不能同时与多个客户端连接,此时就要为服务器端开辟“窗口”,用于接收多个客户端请求,这个“窗口”就是线程池

用线程池实现多点连接

客户端代码不用变,只需要改变服务器端
实现原理就是创建一个线程池,每有一个连接,服务器就创建一个现成用于和客户端连接

  1. 创建一个线程池(这里为不可变大小线程池)

ExecutorService es = Executors.newFixedThreadPool(3);

  1. 写一个子线程把创建流后面的步骤都放进子线程中

class clientThread implements Runnable{
Socket s;
public clientThread(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 s = br.readLine();
System.out.println(s);
ps.println(“echo:”+s);
ps.flush();
ps.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}

客户端复制粘贴几个出来,在中间写一个Sanner用于防止客户端关闭,同时运行即可。

代码有一个的逻辑问题,问题不影响运行我就没改

控制台有如下输出

服务器已开启,等待连接…
127.0.0.1
你好我是客户端
127.0.0.1
你好我是客户端
127.0.0.1
服务器已满载…无法再接入客户端…
你好我是客户端

这里服务器已满载在你好我是客户端的前面是因为
主线程和子线程同时运行,这里可以通过使用线程等待去改进
对程序本身没影响

完整代码

MultiServer.java

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiServer {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(3);

        try{
            ServerSocket server = new ServerSocket(6666);
            System.out.println("服务器已开启,等待连接...");
            int i = 0;
            boolean flag = true;
            //检测连接数不大于3
            while (flag){
                i++;
                Socket s = server.accept();
                System.out.println(s.getInetAddress().getHostAddress()); //获取连接进来的地址
                es.execute(new clientThread(s));
                if(i==3){
                    flag = false;
                    }

            }System.out.println("服务器已满载...无法再接入客户端...");
        }catch (IOException e){
            e.printStackTrace();
        }
    }

}

class clientThread implements Runnable{
    Socket s;
    public clientThread(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 s = br.readLine();
            System.out.println(s);
            ps.println("echo:"+s);
            ps.flush();
            ps.close();
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client.java

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        try{
            Socket s = new Socket("localhost",6666);
            PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            ps.println("你好我是客户端");
            ps.flush();
            System.out.println("请输入姓名:");
            sc.nextLine();
            String s1 = br.readLine();
            System.out.println(s1);
            ps.close();
            br.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_33021025/article/details/89973638
今日推荐