先来一个简单的。下面的程序实现客户端输入多条信息到服务器端
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 public class Server{ 5 public static void main(String[] args) { 6 try{ 7 ServerSocket ss = new ServerSocket(4000);//生成一个ServerSocket对象 8 Socket s = ss.accept(); //接收一个Socket,这个是带阻塞的,没接收到就一直等待 9 InputStream is = s.getInputStream(); //得到socket的输入流,接收数据 10 byte[] buffer = new byte[1024]; //本次试验通过字节流接收数据 11 while(true){ 12 13 int length = is.read(buffer); 14 String str = new String(buffer,0,length).trim(); //取出数据中多余的空格 15 System.out.println(str); 16 } 17 18 }catch(IOException e){ 19 e.printStackTrace(); 20 } 24 } 25 }
客户端:
1 import java.io.*; 2 import java.net.*; 3 4 public class Client{ 5 public static void main(String[] args){ 6 try{ 7 Socket s = new Socket("localhost",4000); //生成一个连接到4000端口的socket 8 OutputStream os = s.getOutputStream(); //得到输出流 9 InputStream is = System.in; //接收控制台的输入作为输出 10 byte[] buffer = new byte[1024]; 11 12 while(true){ 13 14 int length = is.read(buffer); 15 String str = new String(buffer,0,length); 16 // String str= "hello world"; 17 os.write(str.getBytes()); 18 os.flush(); 19 } 20 21 }catch(IOException e){ 22 e.printStackTrace(); 23 } 24 } 25 }
接下来稍微升级一下,创建一个可以接收多个客户端访问的服务器端,主要程序段是将接收Socket的那段放到while循环中,客户端部分不变
实践证明行不通,突然意识到需要用多线程来实现,就是将接收Socket那一段放到线程中,每当接收到一个Socket就起一个线程
1 import java.io.*; 2 import java.net.*; 3 4 public class Server{ 5 public static void main(String[] args) { 6 try{ 7 ServerSocket ss = new ServerSocket(4000); 8 9 while(true){ //将得到socket的程序段放到while循环中,当接收到Socket时起一个线程 10 Socket s = ss.accept(); 11 new Thread(new run1(s)).start(); 12 } 13 }catch(IOException e){ 14 e.printStackTrace(); 15 } 16 } 17 } 18 19 class run1 implements Runnable{ //继承Runnable接口 20 Socket socket ; 21 public run1(Socket socket){ //将Socket当做参数传进去 22 this.socket = socket; 23 } 24 public void run(){ 25 try{ 26 InputStream is = socket.getInputStream(); //得到socket中的输入流 27 byte[] buffer = new byte[1024]; 28 while(true){ 29 int length = is.read(buffer); 30 String str = new String(buffer,0,length).trim(); 31 System.out.println(str); 32 } 33 }catch(IOException e){ 34 e.printStackTrace(); 35 } 36 } 37 }
就下来在深入完成一个客户端和一盒服务器端可以进行互相的读写操作而不受读写顺序的影响,有点像QQ的那种感觉
主要修改的地方是在服务器端加一个输入的线程,客户端和服务器端进行相同的修改加两个线程,输入和输出
服务器端:
View Code
import java.io.*; import java.net.*; public class Server{ public static void main(String[] args) { try{ ServerSocket ss = new ServerSocket(4000); while(true){ Socket s = ss.accept(); new Thread(new run1(s)).start(); new Thread(new run2(s)).start(); } }catch(IOException e){ e.printStackTrace(); } } } class run1 implements Runnable{ Socket socket ; public run1(Socket socket){ this.socket = socket; } public void run(){ try{ InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; while(true){ int length = is.read(buffer); String str = new String(buffer,0,length).trim(); System.out.println(str); } }catch(IOException e){ e.printStackTrace(); } } } class run2 implements Runnable{ Socket socket; public run2(Socket socket){ this.socket = socket; } public void run(){ try{ OutputStream os = socket.getOutputStream(); InputStream is = System.in; byte[] buffer = new byte[1024]; while(true){ int length = is.read(buffer); String str = new String(buffer,0,length); os.write(str.getBytes()); } }catch(IOException e){ e.printStackTrace(); } } }
用户端:
View Code
import java.io.*; import java.net.*; public class Client{ public static void main(String[] args){ try{ Socket s = new Socket("localhost",4000); new Thread(new run3(s)).start(); new Thread(new run4(s)).start(); }catch(IOException e){ e.printStackTrace(); } } } class run3 implements Runnable{ Socket socket; public run3(Socket socket){ this.socket = socket; } public void run(){ try{ OutputStream os = socket.getOutputStream(); InputStream is = System.in; byte[] buffer = new byte[1024]; while(true){ int length = is.read(buffer); String str = new String(buffer,0,length); os.write(str.getBytes()); os.flush(); } }catch(IOException e){ e.printStackTrace(); } } } class run4 implements Runnable{ Socket socket; public run4(Socket socket){ this.socket = socket; } public void run(){ try{ InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; while(true){ int length = is.read(buffer); String str = new String(buffer,0,length).trim(); System.out.println(str); } }catch(IOException e){ e.printStackTrace(); } } }
虽然可以起多个客户端对服务器发送消息但是如果服务器端要回复消息,那么在多个客户端的情况下,消息是随即发送的
接下来在深入,写个服务器接收客户端信息,支持多客户端。接收到的信息发布到全部的客户端上,类似于QQ的多人聊天室。
主要的思想是生成一个arrayList,将新生成的socket加到list中当有客户端向其中写入数据时,遍历所有的socket,向其中发送数据
服务器端程序如下:
1 import java.io.*; 2 import java.net.*; 3 import java.util.*; 4 5 public class ServerPort2{ 6 public static ArrayList<Socket> array = new ArrayList<Socket>(); 7 public static void main(String[] args) { 8 try{ 9 ServerSocket ss = new ServerSocket(4000); 10 11 while(true){ 12 Socket s = ss.accept(); 13 array.add(s); 14 new Thread(new run1(s)).start(); 15 //new Thread(new run2(s)).start(); 16 } 17 }catch(IOException e){ 18 e.printStackTrace(); 19 } 20 } 21 } 22 23 class run1 implements Runnable{ 24 Socket socket ; 25 public run1(Socket socket){ 26 this.socket = socket; 27 } 28 public void run(){ 29 try{ 30 31 InputStream is = socket.getInputStream(); 32 byte[] buffer = new byte[1024]; 33 while(true){ 34 int length = is.read(buffer); 35 String str = new String(buffer,0,length).trim(); 36 System.out.println(str); 37 //将接收到的信息通过arrayList发到每一个客户端去 38 39 sendMessage(str); 40 41 } 42 }catch(IOException e){ 43 System.out.println("one Client is out");//当一个客户端移除时打印信息 44 } 45 } 46 47 public void sendMessage(String str){ 48 try{ 49 for(Socket s : ServerPort2.array){ 50 OutputStream os = s.getOutputStream(); 51 os.write(str.getBytes()); 52 } 53 }catch(IOException e){ 54 ServerPort2.array.remove(socket); 55 }
客户端和上面的客户端一样不做改变。运行结果一切ok,虽然界面差了点但还是实现了向多个客户端写数据的功能。
实验完毕:
总结:
掌握了简单的网络编程
复习了多线程知识
复习了IO流的相关操作