1、网路编程概述
·网络模型 1、OSI参考模型 2、TCP/IP参考模型
·网络通讯要素 1、IP地址 2、端口号 3、传输协议
参考模型图:
传输过程:
2、网络编程_通讯要素
·IP地址:InetAddress 1、网络中设备的标识 2、不易记忆,可用主机名 3、本机回环地址:127.0.0.1 主机名:localhost
·端口号:1、用户标识进程的逻辑地址,不同进程的标识 2、有效端口:0-65535,其中0-1024系统使用或保留端口。
·传输协议:1、通讯的规则 2、常见的协议:TCP,UDP
TCP和UDP的区别:
TCP 面向链接 传输性可靠 传输少量数据 速度慢
UDP 面向无链接 传输性不可靠 传输大量数据 速度快
具体点:
·UDP 1、将数据及源和目的封装成数据包中,不需要建立链接 2、每个数据包的大小限制在64k内 3、因无连接,是不可靠协议 4、不需要建立连接,速度快
·TCP 1、建立链接,形成传输数据的通道 2、在连接中进行大量数据传输 3、通过三次握手完成链接,是可靠协议(想想传呼机) 4、必须建立连接,效率会低
3、网络编程_Socket
·Socket就是为了网络服务提供的一种机制
·通信的两端都有Socket
·网络通信其实就是Socket间的通信
·数据在两个Socket间通过IO传输
·DatagramSocket,DatagramSocket上总是启用UDP广播发送。为了接受广播包,应该将DatagramSocket绑定到通配符地址。
需求:通过UDP传输方式,将一段文字传输出去
注意点:(发送端)1、建UDPSocket服务(25302是发送端的端口):DatagramSocket ds = new DatagramSocket(25302); 2、提供数据,并将数据封装到数据包中 10000是端口:DatagramPacket dp = new DatagramPacket(buf, 0, buf.length, InetAddress.getByName("192.168.1.100"), 10000); 3、通过socket服务的发送功能发送出去:ds.send(dp);4、关闭资源:ds.close();(接收端)1、定义udpscoket服务,通常会监听一个端口 ds = new DatagramSocket(10000)(和数据包的端口一致);2、定义数据,用于存储数据:DatagramPacket dp = new DatagramPacket(b, b.length);3、通过服务的receive的方法将收到的数据存入数据库(阻塞方法)ds.receive(dp);
具体编码:TestSocket.java
1 package com.shanhw.fifthDay; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 import java.net.SocketException; 10 import java.net.UnknownHostException; 11 12 public class TestSocket { 13 public static void main(String[] args) { 14 15 } 16 } 17 18 /** 19 * 通过UDP传输方式,将一段文字传输出去 20 * 1、建立udpSocket服务 21 * 2、提供数据,并将数据封装到数据包中 22 * 3、通过socket服务的发送功能发送出去 23 * 4、关闭资源 24 */ 25 class SendUDP { 26 public static void main(String[] args) { 27 System.out.println("SendUDP"); 28 sendUDP(); 29 } 30 31 public static void sendUDP() { 32 33 DatagramSocket ds = null; 34 DatagramPacket dp = null; 35 try { 36 // 1、建立udpSocket服务 25302是发送端的端口 37 ds = new DatagramSocket(25302); 38 BufferedReader br = new BufferedReader(new InputStreamReader( 39 System.in)); 40 byte[] buf = null; 41 while (true) { 42 try { 43 buf = br.readLine().getBytes(); 44 } catch (IOException e1) { 45 e1.printStackTrace(); 46 } 47 try { 48 // 2、提供数据,并将数据封装到数据包中 10000是端口 49 dp = new DatagramPacket(buf, 0, buf.length, InetAddress 50 .getByName("192.168.1.100"), 10000); 51 } catch (UnknownHostException e) { 52 e.printStackTrace(); 53 } 54 // 3、通过socket服务的发送功能发送出去 55 try { 56 ds.send(dp); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 } 61 62 } catch (SocketException e) { 63 e.printStackTrace(); 64 } finally { 65 ds.close(); 66 } 67 } 68 } 69 70 /** 71 * 定义UDP接收端 72 * 1、定义udpscoket服务,通常会监听一个端口 73 *其实就是给这个接收网络的应用程序 定义数字标识,方便于明确哪些数据包过来可以处理 74 * 2、定义数据包 75 * 3、通过DatagramSocket的receive方法获得数据 76 * 4、关闭资源 77 */ 78 class ReceiveUDP { 79 public static void main(String[] args) { 80 System.out.println("ReceiveUDP"); 81 receiveUDP(); 82 } 83 84 public static void receiveUDP() { 85 DatagramSocket ds = null; 86 try { 87 // 1、建立Socket服务,建立短点,监听一个端口 10000 88 ds = new DatagramSocket(10000); 89 // 2、定义数据包,用于存储数据 90 while (true) { 91 byte[] b = new byte[1024]; 92 DatagramPacket dp = new DatagramPacket(b, b.length); 93 try { 94 // 3、通过服务的receive的方法将收到的数据存入数据库(阻塞方法) 95 ds.receive(dp); 96 } catch (IOException e) { 97 e.printStackTrace(); 98 } 99 // 4、通过数据包的方法获得其数据 100 String ip = dp.getAddress().getHostAddress(); 101 String data = new String(dp.getData(), 0, dp.getLength()); 102 int port = dp.getPort(); 103 System.out.println("receiveUDP:" + ip + " Data:" + data 104 + " 端口:" + port); 105 } 106 } catch (SocketException e) { 107 e.printStackTrace(); 108 } finally { 109 ds.close(); 110 } 111 } 112 }
4、网络编程_Socket_聊天例子(UDP、单进程多线程)
注意点:先开启ReceiveChat端,ds.receive(dp);是一个阻塞方法,他在这里等着呢?SendChat中ds.send(dp);一发送,阻塞着的方法,ds.receive(dp);就唤醒了
具体编码:TestChatSingleProcess.java
1 package com.shanhw.fifthDay; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 import java.net.SocketException; 10 import java.net.UnknownHostException; 11 import java.text.SimpleDateFormat; 12 import java.util.Date; 13 14 public class TestChatSingleProcess { 15 16 /** 17 * 单进程的聊天例子 18 * @throws Exception 19 */ 20 public static void main(String[] args) { 21 ReceiveChat rc = new ReceiveChat(); 22 SendChat sc = new SendChat(); 23 new Thread(rc).start(); 24 new Thread(sc).start(); 25 } 26 } 27 /* 28 * 接收数据段 29 */ 30 class ReceiveChat implements Runnable { 31 32 public void run() { 33 DatagramSocket ds = null; 34 try { 35 ds = new DatagramSocket(10001); 36 } catch (SocketException e) { 37 e.printStackTrace(); 38 } 39 Date d = new Date(); 40 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 41 byte[] buf = new byte[1024]; 42 try { 43 while (true) { 44 DatagramPacket dp = new DatagramPacket(buf, buf.length); 45 ds.receive(dp); 46 String string = new String(dp.getData(), 0, dp.getLength()); 47 String ip = dp.getAddress().getHostAddress(); 48 System.out.println(ip + " 在 " + sdf.format(d) + " 此时说:" + string); 49 } 50 } catch (Exception e) { 51 throw new RuntimeException("发送端失败"); 52 } 53 } 54 } 55 /* 56 * 发送数据端 57 */ 58 class SendChat implements Runnable{ 59 60 public void run() { 61 DatagramSocket ds = null; 62 try { 63 ds = new DatagramSocket(); 64 } catch (SocketException e) { 65 e.printStackTrace(); 66 } 67 DatagramPacket dp= null; 68 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 69 String str = null; 70 try { 71 while((str = br.readLine())!= null){ 72 if("886".equals(str)){ 73 break; 74 } 75 byte[] b = str.getBytes(); 76 dp = new DatagramPacket(b,b.length,InetAddress.getByName("192.168.1.100"),10001); 77 ds.send(dp); 78 } 79 } catch (UnknownHostException e) { 80 e.printStackTrace(); 81 } catch (IOException e) { 82 e.printStackTrace(); 83 }finally{ 84 ds.close(); 85 } 86 } 87 }
5、网络编程_Socket_TCP传输
·Socket和ServerSocket
·建立客户端和服务器端,客户端和服务器端是两个独立的程序
·建立连接后,通过Socket中的IO流精选数据的传输
·关闭Socket 示例图:
例子:(TestTCP.java),此例子------客户端发给服务端信息,此时服务器没有返回信息,比较简单
注意点:1、服务端:通过Socket s = ss.accept();通过accept方法获得链接的客户端对象
1 package com.shanhw.fifthDay; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.OutputStream; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 11 public class TestTCP { 12 13 /** 14 * @param args 15 */ 16 public static void main(String[] args) { 17 18 } 19 } 20 /* 21 * TCP客户端 22 */ 23 class TCPClient{ 24 public static void main(String[] args) throws Exception { 25 Socket sClient = new Socket("192.168.1.100",10003); 26 OutputStream os = sClient.getOutputStream(); 27 os.write("TCPClient Come!".getBytes()); 28 sClient.close(); 29 } 30 } 31 /* 32 * TCP服务器端 33 * 1、建立在服务端的socket服务,ServerSocket(),并监听一个端口 34 * 2、获取连接过来的客户端对象,通过ServerSocket的accept方法,没有连接就会等 35 * 所以这个方法是阻塞式的 36 * 3、如果客户端发过来数据,那么服务端要使用对应的客户端对象…… 37 * 4、关闭服务端(可选) 38 */ 39 class TCPServer{ 40 public static void main(String[] args) throws IOException { 41 ServerSocket ss = new ServerSocket(10003); 42 // 通过accept方法获取链接过来的客户端对象 43 Socket s = ss.accept(); 44 String ip = s.getInetAddress().getHostAddress(); 45 // 获取客户端发过来的数据,那么要使用客户端对象的读取流来读取数据 46 InputStream is = s.getInputStream(); 47 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 48 String string = br.readLine(); 49 System.out.println(ip + ":" + string); 50 // 关闭客户端 51 s.close(); 52 // 关闭服务端 53 ss.close(); 54 } 55 }
客户端服务端互相通信------TestServerMessageClientTCP.java
需求:需求:客户端给服务端发送信息,服务端收到后,反馈信息
1 package com.shanhw.fifthDay; 2 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.io.OutputStream; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 public class TestServerMessageClientTCP { 10 11 /** 12 * 需求:客户端给服务端发送信息,服务端收到后,反馈信息 13 */ 14 public static void main(String[] args) { 15 } 16 } 17 /** 18 * 客户端 19 */ 20 class TCPSocketClient{ 21 public static void main(String[] args) throws Exception { 22 Socket s = new Socket("192.168.1.100", 10004); 23 // 客户端给服务端发送信息 24 OutputStream os = s.getOutputStream(); 25 InputStreamReader isr = new InputStreamReader(System.in); 26 os.write("TCPSocketClient Come!".getBytes()); 27 28 byte[] by = new byte[1024]; 29 // 客户端接收信息 30 InputStream is = s.getInputStream(); 31 int len = is.read(by); 32 System.out.println(new String(by, 0, len)); 33 s.close(); 34 } 35 } 36 /** 37 * 服务端 38 */ 39 class TCPSocketServer{ 40 public static void main(String[] args) throws Exception { 41 ServerSocket ss = new ServerSocket(10004); 42 Socket s = ss.accept(); 43 // 获取IP 44 String ip = s.getInetAddress().getHostAddress(); 45 byte[] by = new byte[1024]; 46 InputStream is = s.getInputStream(); 47 int len = is.read(by); 48 System.out.println("IP:" + ip + " " + new String(by, 0, len)); 49 Thread.sleep(5000); 50 // 服务器发送信息 51 OutputStream os = s.getOutputStream(); 52 os.write("TCPSocketServer Come!".getBytes()); 53 // 关闭客户端 54 s.close(); 55 } 56 }
自己做了一个TCP聊天的例子------TestTCPChatSingleProcess.java
1 package com.shanhw.fifthDay; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.InputStreamReader; 6 import java.io.OutputStreamWriter; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 10 public class TestTCPChatSingleProcess { 11 12 /** 13 * TCP:聊天 14 */ 15 public static void main(String[] args) { 16 TCPChatServer ts = new TCPChatServer(); 17 new Thread(ts).start(); 18 TCPChatClient tc = new TCPChatClient(); 19 new Thread(tc).start(); 20 } 21 } 22 /** 23 * TCP:客户端 24 */ 25 class TCPChatClient implements Runnable{ 26 27 public void run() { 28 try { 29 System.out.println("Client……"); 30 Socket socket = new Socket("192.168.1.100", 10005); 31 // 键盘录入流 32 BufferedReader br = new BufferedReader(new InputStreamReader( 33 System.in)); 34 // 要写入服务端的输出流 35 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket 36 .getOutputStream())); 37 // 定义socket读取流,服务器端返回的信息 38 BufferedReader bufR = new BufferedReader(new InputStreamReader(socket 39 .getInputStream())); 40 String len = null; 41 while ((len = br.readLine()) != null) { 42 if ("over".equals(len)){ 43 System.out.println("Client 关闭成功"); 44 break; 45 } 46 bw.write(len); 47 bw.newLine(); 48 bw.flush(); 49 50 String serverMessage = bufR.readLine(); 51 System.out.println("Sever Say :" + serverMessage); 52 } 53 54 br.close(); 55 // 关闭服务端 56 socket.close(); 57 } catch (Exception e) { 58 throw new RuntimeException("客户端运行时错误"); 59 } 60 } 61 } 62 /** 63 * TCP:服务端 64 */ 65 class TCPChatServer implements Runnable{ 66 67 public void run() { 68 try { 69 System.out.println("Server……"); 70 ServerSocket ss = new ServerSocket(10005); 71 // 得到客户端socket对象 72 Socket socket = ss.accept(); 73 // socket读取流 74 BufferedReader bufIn = new BufferedReader(new InputStreamReader(socket 75 .getInputStream())); 76 // 要写入服务端的输出流 77 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( 78 socket.getOutputStream())); 79 // 键盘录入流 80 BufferedReader br = new BufferedReader(new InputStreamReader( 81 System.in)); 82 String len = null; 83 while ((len = bufIn.readLine()) != null) { 84 System.out.println("Clinet Say:" + len); 85 if ("over".equals(len)) { 86 System.out.println("Server 关闭成功"); 87 break; 88 } 89 bw.write(br.readLine()); 90 bw.newLine(); 91 bw.flush(); 92 } 93 bufIn.close(); 94 // 关闭客户端,选择性关闭服务端 95 socket.close(); 96 } catch (Exception e) { 97 throw new RuntimeException("服务端运行时错误"); 98 } 99 } 100 }
6、网络编程_Socket_TCP_上传图片
为了演示方便,放到一个java文件里面了
例子:UploadClient.java 和UploadServer.java
此例子要注意:
1、定义了一个结束标记符,(Socket的方法)shutdownOutput()
2、shutdownOutput():关闭客户端输出流,其实就是在流里面加了一个结束标记(-1)
1 package com.shanhw.fifthDay; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.InputStreamReader; 10 import java.io.OutputStream; 11 import java.io.PrintWriter; 12 import java.net.ServerSocket; 13 import java.net.Socket; 14 import java.net.UnknownHostException; 15 16 public class TestTCPUpload { 17 18 /** 19 * @param args 20 */ 21 public static void main(String[] args) {} 22 } 23 class UploadClient { 24 25 /** 26 * 客户端:上传文件 27 */ 28 public static void main(String[] args) { 29 File file = new File("E:\\Workspaces\\IMG_0019.JPG"); 30 FileInputStream fis = null; 31 Socket s = null; 32 try { 33 s = new Socket("127.0.0.1",10006); 34 if(file.exists()){ 35 file.createNewFile(); 36 } 37 fis = new FileInputStream(file); 38 OutputStream os = s.getOutputStream(); 39 byte[] buf = new byte[1024]; 40 int len = 0; 41 while((len=fis.read(buf)) !=-1){ 42 os.write(buf,0,len); 43 os.flush(); 44 } 45 // 关闭客户端输出流,其实就是在流里面加了一个结束标记(-1) 46 s.shutdownOutput(); 47 48 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); 49 System.out.println(br.readLine()); 50 } catch (UnknownHostException e) { 51 e.printStackTrace(); 52 } catch (IOException e) { 53 e.printStackTrace(); 54 }finally{ 55 try { 56 fis.close(); 57 s.close(); 58 } catch (IOException e) { 59 e.printStackTrace(); 60 } 61 } 62 } 63 } 64 class UploadServer { 65 66 /** 67 * 服务端(客户端上传文件到地处) 68 */ 69 public static void main(String[] args) { 70 File f = new File("E:\\Workspaces\\ServerSocket\\","xx.jpg"); 71 ServerSocket ss = null; 72 FileOutputStream fos = null; 73 try { 74 ss = new ServerSocket(10006); 75 Socket socket = ss.accept(); 76 InputStream is = socket.getInputStream(); 77 if(f.exists()){ 78 f.createNewFile(); 79 } 80 fos = new FileOutputStream(f); 81 byte[] buf = new byte[1024]; 82 int len = 0; 83 while((len = is.read(buf)) != -1){ 84 fos.write(buf,0,len); 85 fos.flush(); 86 } 87 PrintWriter pw = new PrintWriter(socket.getOutputStream()); 88 pw.print("上传成功"); 89 pw.close(); 90 } catch (IOException e) { 91 e.printStackTrace(); 92 }finally{ 93 try { 94 fos.close(); 95 ss.close(); 96 } catch (IOException e) { 97 e.printStackTrace(); 98 } 99 } 100 } 101 }