网络编程的三要素:
- ip地址:唯一标识网络上的每一台计算机
- 端口号:计算机中应用的标号(代表一个应用程序),0-1024系统使用或者保留端口,有效端口0-65535(short)
- 通信协议:通信的规则 TCP UDP
UDP:相当于发短信,不需要建立连接,数据包的大小限制在64k内,效率高,不安全,容易丢包
TCP:相当于打电话,需要建立连接,效率相对较低,数据传输安全,三次握手完成。
下面使用TCP进行网络通信:
服务端:
1 public static void main(String[] args) throws Exception { 2 //创建服务端的对象 3 ServerSocket ss = new ServerSocket(8000); 4 //等待客户端的接入 5 Socket client = ss.accept(); 6 //从输入流中得到数据 7 InputStream is = client.getInputStream(); 8 byte[] by = new byte[1024]; 9 int len = is.read(by); 10 String str = new String(by,0,len); 11 System.out.println(str); 12 //关闭 13 client.shutdownInput(); 14 is.close(); 15 client.close(); 16 17 }
客户端:
1 public static void main(String[] args) throws Exception { 2 //创建客户端套接字对象,给定ip地址 3 Socket client = new Socket("192.168.6.166",8000); 4 //获取客户端的输出流 5 OutputStream os = client.getOutputStream(); 6 //向输出流中写入数据 7 os.write("在?".getBytes()); 8 os.flush(); 9 //切断输出流 10 client.shutdownOutput(); 11 //关闭流对象,关闭套接字 12 is.close(); 13 os.close(); 14 client.close(); 15 16 }
通过上面的代码能够实现基本的发送信息,和接收信息。不过只能客户端发送信息,服务器被动接收信息,下面来实现客户端和服务器互相发送信息:
服务器端:
1 public static void main(String[] args) throws IOException { 2 ServerSocket ss = new ServerSocket(8000); 3 Scanner sc = new Scanner(System.in); 4 System.out.println("服务器启动!"); 5 Socket s = ss.accept(); 6 OutputStream os = s.getOutputStream(); 7 InputStream is = s.getInputStream(); 8 boolean bool = true; 9 while(bool){ 10 //服务器接收信息 11 byte[] bt = new byte[1024]; 12 int length = is.read(bt); 13 System.out.println(" "+new String(bt,0,length)+":客户端"); 14 //服务器发送信息 15 System.out.println("服务器:"); 16 os.write(sc.next().getBytes()); 17 os.flush(); 18 } 19 s.shutdownInput(); 20 is.close(); 21 os.close(); 22 s.close(); 23 ss.close(); 24 25 }
客户端:
1 public static void main(String[] args) throws UnknownHostException, IOException { 2 System.out.println("客户端启动"); 3 Socket client = new Socket("127.0.0.1",8000); 4 Scanner sc = new Scanner(System.in); 5 boolean bool = true; 6 OutputStream os = client.getOutputStream(); 7 InputStream is = client.getInputStream(); 8 while(bool){ 9 //客户端发送信息 10 System.out.println("客户端:"); 11 String str = sc.next(); 12 os.write(str.getBytes()); 13 os.flush(); 14 //客户端接收信息 15 byte[] by = new byte[1024]; 16 int index = is.read(by); 17 System.out.println(" "+new String(by,0,index)+":服务器"); 18 } 19 client.shutdownOutput(); 20 os.close(); 21 is.close(); 22 sc.close(); 23 client.close(); 24 }
使用上面的方式进行通信,实现结果:
客户端:
服务器:
这样实现了两端相互通信的要求,如果一方连续发送两条信息的时候,这个程序就会开始出现问题。于是使用线程解决这个问题,具体如下:
客户端:
1 public class servletSockettest { 2 public static void main(String[] args) throws IOException { 3 ServerSocket ss = new ServerSocket(8888); 4 System.out.println("服务器启动!"); 5 final Socket s = ss.accept(); 6 boolean b = true; 7 InputStream is = s.getInputStream(); 8 //服务器把输入放入线程里面执行,不会影响主线程的接收信息功能 9 Thread t = new Thread(){ 10 OutputStream os = s.getOutputStream(); 11 Scanner sc = new Scanner(System.in); 12 @Override 13 public void run() { 14 // TODO Auto-generated method stub 15 boolean b = true; 16 while(b){ 17 try { 18 System.out.print("服务器输入:"); 19 os.write(sc.next().getBytes()); 20 os.flush(); 21 } catch (IOException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 } 26 } 27 }; 28 t.start(); 29 while(b){ 30 byte[] bt = new byte[1024]; 31 int length = is.read(bt); 32 String str = new String(bt,0,length); 33 System.out.println(" "+str+":客户端"); 34 } 35 36 37 is.close(); 38 s.shutdownInput(); 39 s.close(); 40 ss.close(); 41 42 } 43 }
客户端:
1 public class Sockettest { 2 public static void main(String[] args) throws UnknownHostException, IOException { 3 final Socket client = new Socket("192.168.6.166",8888); 4 Scanner sc = new Scanner(System.in); 5 System.out.println("客户端启动"); 6 OutputStream os = client.getOutputStream(); 7 //新建一个线程用来接收信息,不影响主线程的输入发送信息。 8 Thread t = new Thread(){ 9 InputStream is = client.getInputStream(); 10 @Override 11 public void run() { 12 // TODO Auto-generated method stub 13 boolean b = true; 14 while(b){ 15 try { 16 byte[] bt = new byte[1024]; 17 int length = is.read(bt); 18 String str = new String(bt,0,length); 19 System.out.println(" "+str+":服务器"); 20 } catch (IOException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 } 25 } 26 }; 27 t.start(); 28 boolean b = true; 29 while(b){ 30 System.out.print("客户端输入:"); 31 os.write(sc.next().getBytes()); 32 os.flush(); 33 } 34 os.close(); 35 client.shutdownOutput(); 36 client.close(); 37 } 38 }
运行结果:
客户端
服务器:
这样就可以实现基本上的通信了。如果有兴趣,可以结合JFrame窗体,实现多个窗口相互聊天,不再使界面这么难看。