网络_套接字_java
1 由于(https://www.cnblogs.com/S-Mustard/p/11924227.html)讲到通过telnet访问百度首页,现在通过java代码来实现访问百度服务,获取首页信息。
try(Socket s=new Socket("www.baidu.com",80); Scanner in =new Scanner(s.getInputStream(),"UTF-8"); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));){ StringBuffer sb = new StringBuffer(); sb.append("GET https://www.baidu.com HTTP/1.1\r\n").append("Host:"+ "www.baidu.com" + "\r\n").append("\r\n"); out.write(sb.toString()); out.flush(); while(in.hasNextLine()){ System.out.println(in.nextLine()); } }
2 java实现套接字服务器,由telnet工具建立连接,发送消息
Boolean done=false; ServerSocket s =new ServerSocket(8189); Socket incoming=s.accept();// 此时如果telnet不发送任何的连接,即程序会停止在此处,不往下执行,即阻塞状态 InputStream inStream=incoming.getInputStream(); OutputStream outStream=incoming.getOutputStream(); Scanner in=new Scanner(inStream,"UTF-8"); PrintWriter out=new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
while(!done && in.hasNextLine()) {//in.hasNextLine()是阻塞状态,如果telnet客户端不进行任何的输入 String line=in.nextLine(); out.println("echo:"+line); if(line.trim().equals("bye")) done=true; }
启动程序后,用telnet访问
1) 不进行任何的操作,程序阻塞
2) 进行连接,输入telnet localhost 8189,不进行任何的输入文字,程序会阻塞
3) 输入文字,进入循环内部,一次循环结束,如果不继续输入文字,又是阻塞状态
4) 输入bye,进入循环内部,执行到done=true,结束整个程序,ServerSocket不存在,所以会看到遗失对主机的连接。
3 java写客户端和服务器端,客户端访问服务器端
客户端
try(Socket s=new Socket("localhost",8189); Scanner in =new Scanner(s.getInputStream(),"UTF-8"); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));){ Scanner sysin=new Scanner(System.in); System.out.println("请输入:"); while(sysin.hasNextLine()) { String line = sysin.nextLine(); line=line+"\r\n"; System.out.println("输入:"+line); out.write(line); out.flush(); System.out.println(in.nextLine()); } }
服务器端
Boolean done=false; ServerSocket s =new ServerSocket(8189); Socket incoming=s.accept(); System.out.println("==============="); InputStream inStream=incoming.getInputStream(); OutputStream outStream=incoming.getOutputStream(); Scanner in=new Scanner(inStream,"UTF-8"); PrintWriter out=new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true); while(!done && in.hasNextLine()) { String line=in.nextLine(); System.out.println("回传:"+line); out.println("echo:"+line); if(line.trim().equals("bye")) done=true; }
分别启动客户端和服务器端,在客户端的控制台输入字符,可以看到服务器的echo,当客户端输入bye后,服务器端会停止运行,此时客户端程序因为连不上服务器端会报错停止。
客户端结果
服务器端结果
4 服务器支持多客户端编程
当我们尝试再打开一个cmd用telnet连接server时,发现根本得不到反应,只有第一个cmd才能得到反应,而且当第一个cmd关闭连接时,in.hasNextLine()为false
,整个程序被停止。
如何让我们写的程序能支持多个客户端,就是创建多个Socket incoming=s.accept();来对我们的多个客户端做出反应。
第一想法是用for循环创建多个Socket ,但是有一个问题,这是排队的形式,只有当第一个客户端关闭时,第二个客户端的输入才能得到第二个服务器的反应。也就是当第一个循环体内代码走完时,才能进入第二个循环体内,第二个循环体内的服务器端才能为第二个客户端服务。
如下代码做测试,启动服务,用telnet工具访问服务。
ServerSocket s =new ServerSocket(8189); for(int i=0;i<2;i++){
Boolean done=false; Socket incoming=s.accept(); System.out.println("==============="); InputStream inStream=incoming.getInputStream(); OutputStream outStream=incoming.getOutputStream(); Scanner in=new Scanner(inStream,"UTF-8"); PrintWriter out=new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true); while(!done && in.hasNextLine()) { String line=in.nextLine(); System.out.println("回传:"+line); out.println("echo:"+line); if(line.trim().equals("bye")) done=true; } System.out.println("停止运行"); }
那么如上是实现不了为多个客户端同时服务的,就想到线程的方式,可以同时为多个客户端服务。
public class Test { public static void main(String[] agrs) throws IOException { ServerSocket s =new ServerSocket(8189); for(int i=0;i<2;i++){// 先支持两个客户端的访问 new Thread(new ImplRunnable(s)).start(); } } static class ImplRunnable implements Runnable{ private ServerSocket s ; public ImplRunnable(ServerSocket s){ this.s=s; } @Override public void run() { try{ Boolean done=false; Socket incoming=s.accept(); System.out.println("==============="); InputStream inStream=incoming.getInputStream(); OutputStream outStream=incoming.getOutputStream(); Scanner in=new Scanner(inStream,"UTF-8"); PrintWriter out=new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true); while(!done && in.hasNextLine()) { String line=in.nextLine(); System.out.println("回传:"+line); out.println("echo:"+line); if(line.trim().equals("bye")) done=true; } System.out.println("停止运行"); }catch (Exception e) { e.printStackTrace(); } } } }
测试结果如下