Socket网络编程
1.通过 URL对象的OpenStream()方法可以得到指定资源的输入流,通过输入流可以读取、访问网络上的数据。
1 public class URLTest02 { 2 3 public static void main(String[] args) { 4 5 try { 6 //创建一个URL实例 7 URL url = new URL("http://www.baidu.com"); 8 //通过URL的openStream方法获取URL的字节输入流 9 InputStream is = url.openStream(); 10 //将字节输入流转换为字符输入流 11 InputStreamReader isr = new InputStreamReader(is,"UTF-8"); 12 //为字符输入流添加缓冲 13 BufferedReader br = new BufferedReader(isr); 14 String data = br.readLine();//读取数据 15 while(data!=null){//循环读取数据 16 System.out.print(data); 17 data = br.readLine(); 18 } 19 br.close(); 20 isr.close(); 21 is.close(); 22 } catch (MalformedURLException e) { 23 e.printStackTrace(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 28 } 29 30 }
2. 基于TCP的网络编程
TCP协议是面向连接的、可靠的、有序的,以字节流的方式发送数据。
基于TCP协议实现网络通信的类:客户端的Socket类,服务器端的SeverSocket类
基本步骤:
(1) 服务器端建立服务端监听Socket
(2)服务器端等待并接受请求
(3) 客户端创建连接Socket,向服务器端发送请求
(4) 服务器端接收请求,并创建连接Socket
(5) 传送与接收数据
(6) 关闭Socket及相关资源
应用多线程来实现服务器与客户端之间的通信
基本步骤:
(1)服务器端创建ServerSocket,循环调用accept()等待客户端连接
(2)客户端创建一个Socket并请求和服务器端连接
(3)服务器端接受客户端请求,创建Socket与该客户建立连接
(4)建立连接的两个Socket在一个单独的线程上对话
(5)服务器端继续等待新的连接
1 /* 2 * 基于TCP协议的Socket通信,实现用户登录 3 * 服务器端 4 */ 5 public class SocketServer { 6 7 public static void main(String[] args) { 8 9 Socket socket = null; 10 ServerSocket serverSocket = null; 11 int count = 0; 12 try { 13 // 1. 创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口 14 serverSocket = new ServerSocket(8888); 15 System.out.println("服务器即将启动,等待客户连接。。。"); 16 // 循环监听等待客户端的连接 17 while (true) { 18 // 2. 调用accept()方法开始监听,等待客户端的连接 19 socket = serverSocket.accept(); // 此时会堵塞 20 // 创建一个新的线程 21 ServerThread serverThread = new ServerThread(socket); 22 // 启动线程 23 serverThread.start(); 24 count++; 25 System.out.println("客户端的数量为:"+count); 26 InetAddress address = socket.getInetAddress(); 27 System.out.println("客户端IP:"+address.getHostAddress()); 28 29 } 30 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 }
1 /* 2 * 基于TCP协议的Socket通信,实现用户登录 3 * 客户端 4 */ 5 public class SocketClient { 6 7 public static void main(String[] args) { 8 9 try { 10 //1. 创建客户端Socket,指定服务器地址和端口 11 Socket socket = new Socket("localhost",8888); 12 //2. 获取输出流,向服务器发送信息 13 OutputStream os = socket.getOutputStream();//字节输出流 14 PrintWriter pw = new PrintWriter(os); 15 16 pw.write("用户名:lah;密码:123456"); 17 System.out.println(); 18 pw.flush(); 19 socket.shutdownOutput();//关闭输出流 20 21 //获取输入流,读取服务器端的响应信息 22 InputStream is = socket.getInputStream(); 23 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 24 String info = null; 25 while((info = br.readLine())!=null){//循环读取客户端信息 26 System.out.println("我是客户端,服务器说:"+info); 27 } 28 29 //4. 关闭资源 30 br.close(); 31 is.close(); 32 pw.close(); 33 os.close(); 34 socket.close(); 35 36 } catch (UnknownHostException e) { 37 e.printStackTrace(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 42 } 43 }
1 /* 2 * 服务器线程处理类 3 */ 4 public class ServerThread extends Thread { 5 // 和本线程相关的Socket 6 Socket socket = null; 7 8 public ServerThread(Socket socket) { 9 this.socket = socket; 10 } 11 12 // 线程执行的操作,响应客户端的请求 13 @Override 14 public void run() { 15 16 InputStream is = null; 17 InputStreamReader isr = null; 18 BufferedReader br = null; 19 20 OutputStream os = null; 21 PrintWriter pw = null; 22 String info = null; 23 24 try { 25 // 3. 获取输入流,用来读取客户端所发送的信息 26 is = socket.getInputStream(); 27 isr = new InputStreamReader(is); 28 br = new BufferedReader(isr); 29 30 while ((info = br.readLine()) != null) {// 循环读取客户端信息 31 System.out.print("我是服务器,客户端说:" + info); 32 } 33 socket.shutdownInput();// 关闭输入流 34 // 获取输出流,响应客户端的请求 35 os = socket.getOutputStream(); 36 pw = new PrintWriter(os); 37 pw.write("欢迎您!"); 38 pw.flush(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } finally { 42 43 try { 44 // 5. 关闭相关的资源 45 if (pw != null) 46 pw.close(); 47 if (os != null) 48 os.close(); 49 if (br != null) 50 br.close(); 51 if (isr != null) 52 isr.close(); 53 if (is != null) 54 is.close(); 55 if (socket != null) 56 socket.close(); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 } 61 62 } 63 64 }
3. UDP编程
进行数据传输时,首先需要将传输的数据定义成数据报,在数据报中指定数据要到达的Socket(主机地址和端口号),然后再将数据报发送出去。
DatagramPacket: 表示数据包
DatagramSocket: 进行端到端通信的类
服务器端实现步骤:
(1)创建DatagramSocket,指定端口号
(2)创建DatagramPacket
(3)接收客户端发送的数据信息
(4)读取数据
1 /* 2 * 基于UDP的用户登录 3 */ 4 public class UDPServer { 5 6 public static void main(String[] args) throws IOException { 7 //1. 创建服务器端DatagramSocket,指定端口 8 DatagramSocket socket = new DatagramSocket(8800); 9 //2. 创建数据报,用于接收客户端发送的数据 10 byte[] data = new byte[1024];//创建字节数组,指定接收数据报的大小 11 DatagramPacket packet = new DatagramPacket(data, data.length); 12 //3. 接收客户端发送的数据 13 System.out.println("服务器端已经启动,等待客户端发送数据****"); 14 socket.receive(packet);//此方法在接收到数据报之前会一直阻塞 15 //4. 读取数据 16 String info = new String(data, 0, packet.getLength()); 17 System.out.println("我是服务器,客户端说:"+info); 18 19 /* 20 * 向客户端响应数据 21 */ 22 //1. 定义客户端的地址、端口号、数据 23 InetAddress address = packet.getAddress(); 24 int port = packet.getPort(); 25 byte[] dataTo = new byte[1024]; 26 dataTo="欢迎您!".getBytes(); 27 DatagramPacket packetTo = new DatagramPacket(dataTo,dataTo.length, address, port); 28 socket.send(packetTo); 29 30 socket.close(); 31 } 32 33 }
客户端实现步骤:
(1)定义发送的信息
(2)创建DatagramPacket,包含要发送的信息
(3)创建DatagramSocke
(4)发送数据
1 /* 2 * 客户端,基于UDP的用户登录 3 */ 4 public class UDPClient { 5 6 public static void main(String[] args) throws IOException { 7 // 1. 定义服务器的地址,端口号、数据 8 InetAddress address = InetAddress.getByName("localhost"); 9 int port = 8800; 10 byte[] data = "用户名:admin;密码:123".getBytes(); 11 //2. 创建数据报,包含发送的数据信息 12 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); 13 //3. 创建DatagramSocket对象 14 DatagramSocket socket = new DatagramSocket(); 15 //4. 向服务器端发送数据报 16 socket.send(packet); 17 18 /* 19 * 接收服务器端响应的数据 20 */ 21 // 22 byte[] data2 = new byte[1024]; 23 DatagramPacket packet2 = new DatagramPacket(data2, data2.length); 24 socket.receive(packet2); 25 String reply = new String(data2, 0, packet2.getLength()); 26 System.out.println("我是客户端,服务器说:"+reply); 27 socket.close(); 28 } 29 30 }