明确一点,在进行网络编程时,一定是先有服务器,客户端再去连服务器。以后写肯定都有两个Demo(两个main线程),一个是连服务器的,一个是连客户端的。
ServerSocket的构造方法
构造器描述ServerSocket()创建未绑定服务的 套接字ServerSocket(int port)创建绑定到指定端口的服务器 套接字ServerSocket(int port,int backlog)创建服务器套接字 并 使用指定的待办事项将其绑定到指定的本地端口ServerSocket(int port,int backlog,InetAddress bindAddr)创建具有指定端口的服务器,监听backlog和要绑定的本地IP地址方法很多,有需求可以查看API,常用方法有如下
Soket accept(); 等待客户端连接, 此方法会导致线程阻塞, 直到一个新的客户端连接成功,return Socket对象后,线程继续执行 void close(); 释放占用的端口,关闭服务器。就会执行四次挥手操作,稳稳地关闭服务器 变量和类型方法描述Socketaccept()侦听对此套接字的连接并接受它voidclose()关闭此套接字InetAddressgetInetAdress()返回此服务器套接字的本地地址booleanisClosed()返回ServerSocket的关闭状态………连接靠两个Demo实现,先创建服务器端,后创建客户端
//服务器 public class Demo { public static void main(String[] args) throws IOException { //搭建服务器,写入端口号 ServerSocket serverSocket = new ServerSocket(55533); //等待客户端连接,会阻塞,直到一个客户端连接成功 Socket socket = serverSocket.accept(); System.out.println("服务器程序执行结束"); } }必须先运行以上代码后,运行下面代码才能连接
//客户端 public class ClientDemo { public static void main(String[] args) throws IOException { //本机的IP地址默认为 127.0.0.1 Socket socket = new Socket("127.0.0.1",55533); } }Socket类的常用方法
1.OutputStream getOutputStream(); 返回的是,指向通信的另一端点的输出流 2.InputStream getInputSream(); 返回的是,指向通信的另一端点的输入流 3.void close(); 关闭 套接字 注意: 1. 在网络编程时,获取输入流的操作,对于客户端与服务器来说是相对的 2. 客户端的输入流,输入的是服务器的输出流 输出的内容 3. 客户端的输出流,输出的是服务器的输入流, 所以,在使用时,需要注意以下一点规则: 客户端与服务器获取流的顺序必须是相反的,只能是一端收一段发,不同两端都发/收,否则会卡在这; 但是可以选择多线程进行,一个接收一个发送同时将进行。 例如:客户端先得到了输入流,那服务器端必须先获取输出流 使用最多的还是getInputStream()/getOutputStream()方法 变量和类型方法描述voidclose()InputStreamgetInputStream()返回套接字的输入流OutputStreamgetOutputStream()返回此套接字的输出流intgetPort()返回此套接字的远程端口号booleanisBound()返回套接字的绑定状态booleanisClosed()返回套接字的连接状态booleanisConnected()返回套接字的连接状态………代码演示:
//服务器端 public class Demo { public static void main(String[] args) throws IOException { //搭建服务器,ServerSocket()需要传入 端口号(0-65565) ServerSocket serverSocket = new ServerSocket(55533); System.out.println("服务器启动完毕"); //等待客户端连接,会阻塞,直到一个客户端连接成功 Socket socket = serverSocket.accept(); System.out.println("一个客户端连接了"); //获取一个输出流 OutputStream os = socket.getOutputStream(); //把输出流转换为打印流,转换为打印流是为了可以输入一串字符 PrintStream ps = new PrintStream(os); //给客户端发送消息 ps.println("客户端你好"); //接收 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String txet = br.readLine(); System.out.println("服务器端接收的信息:"+txet); System.out.println("服务器程序执行结束"); } } //客户端 public class ClientDemo { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1",55533); InputStream is = socket.getInputStream(); //使用BufferedReader接收可以一次接收一行 BufferedReader br = new BufferedReader(new InputStreamReader(is)); String text = br.readLine(); System.out.println("客户端接收到消息:"+text); //发送 OutputStream os = socket.getOutputStream(); PrintStream ps = new PrintStream(os); ps.println("服务器你好"); } }服务器能同时服务多个客户端怎么办,使用循环等待客户端连接必不可少。注意客户端与服务器端必须是一端输入一端接收的机制
//就不进行接收演示了,就是接 收,交替执行 public class Demo { public static void main(String[] args) throws IOException { //搭建服务器 ServerSocket serverSocket = new ServerSocket(55533); System.out.println("服务器启动完毕"); while (true) { //等待客户端连接,会阻塞,直到一个客户端连接成功 //服务器可以抗住很多的客户端 Socket socket = serverSocket.accept(); // 启动一个子线程与客户端进行交互,无限循环就无限启动子线程,主线程就能一直等待客户端连接 // 提高服务器的处理多个客户端的能力 new Thread(new Runnable() { @Override public void run() { try { InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } } }).start(); System.out.println("一个客户端连接了"); } } }