《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端
1、Socket简介
在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。也就是说在Java环境下我们实现基于TCP/IP协议的网络编程需要采用Socket机制。Socket编程比基于URL的网络编程提供了更高的传输效率、更强大的功能和更灵活的控制,但是却要更复杂一些。由于Java本身的特殊性,Socket编程在Java中可能已经是层次最低的网络编程接口,在Java屮要直接操作协议中更低的层次,需要使用Java的本地方法调用 (JNI),在这里就不予讨论了。
Android中进行Socket编程与普通Java程序所进行的Socket编程的方式保持一致,不同的是数据的来源以及显示上有所区别。采用Java语言开发的一些网络编程的应用比如最经典的聊天室应用可以很容易地移植到Android平台上。而由于TCP协议要比UDP协议的应用广泛,如常用的HTTP、FTP、SMTP等协议都是采用TCP协议,因此这里主要介绍Android中基于 TCP协议的Socket编程。
Socket通常用来实现C/S结构。使用Socket进行Client/Server程序设计的一般连接过程是这样的:Server端监听某个端口是否有连接请求,Client端向Server端发出连接请求,Server端向Client端发回Accept (接受)消息,一个连接就建立起来了。Server端和Client端都可以通过Send、Write等方法与对方通信。Java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。
2、Socket和ServerSocket
在Java网络通信技术中,有一对非常般配的技术——Socket和ServerSocket
网络编程可以分为创建Socket、打开连接Socket的输入流和输出流,对Socket进行编程,关闭Socket。
ServerSocket用于服务器端,accept方法会返回一个客户端的Socket对象实例。这个时候服务器和客户端的连接就建立成功啦。
3、程序实现及效果:
客户端程序:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.io.OutputStream; 6 import java.io.PrintStream; 7 import java.net.ConnectException; 8 import java.net.Socket; 9 10 public class KeSocket 11 { 12 public static void main(String args[]) 13 { 14 try 15 { 16 Socket s= new Socket("127.0.0.1",2007); 17 InputStream is = s.getInputStream(); 18 OutputStream os = s.getOutputStream(); 19 20 PrintStream ps = new PrintStream(os); 21 ps.println("hello"); 22 //DataInputStream dis = new DataInputStream(is); 23 //String request = dis.readLine(); 24 BufferedReader dis = new BufferedReader(new InputStreamReader(is)); 25 String request = dis.readLine(); 26 System.out.println(request); 27 s.close(); 28 } 29 catch(ConnectException e) 30 { 31 System.out.println("异常"+e); 32 } 33 catch(IOException ee) 34 { 35 System.out.println("异常"+ee); 36 } 37 catch(Exception eee) 38 { 39 System.out.println("异常"+eee); 40 } 41 } 42 }
服务器端程序:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.io.OutputStream; 6 import java.io.PrintStream; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 10 11 public class ServerSocket1 12 { 13 public static void main(String args[]) 14 { 15 try 16 { 17 ServerSocket ss = new ServerSocket(2007); 18 while(true) { 19 Socket s = ss.accept(); 20 InputStream is= s.getInputStream(); 21 OutputStream os= s.getOutputStream(); 22 23 BufferedReader dis = new BufferedReader(new InputStreamReader(is)); 24 String request = dis.readLine(); 25 System.out.println(request); 26 PrintStream ps = new PrintStream(os); 27 ps.println("Bye"); 28 s.close(); 29 ss.close(); 30 } 31 } 32 catch(IOException e) 33 { 34 System.out.println("异常"+e); 35 } 36 catch(Exception ee) 37 { 38 System.out.println("异常"+ee); 39 } 40 } 41 }
不打开服务器端,显然客户端连接失败:
异常java.net.ConnectException: Connection refused: connect
打开服务器端程序后,
服务器端显示:
hello
异常java.net.SocketException: Socket is closed
客户端显示:
Bye
4、多客户端连接
在实际的应用中,往往有许多客户端向服务器发送请求,服务器会启动一个专门的服务线程来响应客户端的请求,同时服务器本省在启动线程之后,马上进入监听状态。
DuoServer.java 演示多客户请求服务器的过程,代码如下:
1 import java.net.*; 2 import java.io.*; 3 public class DuoServer 4 { 5 public static void main(String args[]) 6 { 7 boolean connected=true; 8 try 9 { 10 ServerSocket ss = new ServerSocket(2007); 11 int clientnum = 0; 12 while(connected) { 13 ServerThread st = new ServerThread(ss.accept(),clientnum); 14 st.start(); 15 clientnum++; 16 System.out.println(clientnum); 17 18 } 19 } 20 catch(Exception e) 21 { 22 System.out.println("异常"+e); 23 } 24 } 25 } 26 class ServerThread extends Thread 27 { 28 private Socket s; 29 int clientnum; 30 public ServerThread(Socket s,int num) 31 { 32 this.s=s; 33 clientnum=num+1; 34 } 35 public void run() 36 { 37 try 38 { 39 InputStream is=s.getInputStream(); 40 OutputStream os=s.getOutputStream(); 41 BufferedReader dis = new BufferedReader(new InputStreamReader(is)); 42 String request=dis.readLine(); 43 System.out.println(request); 44 PrintStream ps=new PrintStream(os); 45 ps.println("Bye"); 46 s.close(); 47 } 48 catch(Exception e) 49 { 50 System.out.println("异常"+e); 51 } 52 } 53 }
多次运行客户端程序,调用3次后可以看到服务器端结果:
1 hello 2 hello 3 hello