黑马Java学习笔记之-----网络编程
---------------------- android培训、java培训、期待与您交流! ----------------------
IP地址:
格式:IP地址= 网络地址+主机地址 (IP地址使用32位长度二进制数据表示)
网络号:用于识别主机所在的网络。
主机号:用于识别该网络中的主机。
IP地址分为5类,A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验。IP地址的范围:
InetAddress类:
主要表示IP地址,包括:Inet4Address和Inet6Address。
1 //测试InetAddress类 2 3 import java.net.InetAddress; 4 5 public class InetAddressTest 6 { 7 public static void main(String[] args)throws Exception //抛出异常 8 { 9 testInet(); 10 } 11 12 public static void testInet()throws Exception //抛出异常 13 { 14 InetAddress localAdd = InetAddress.getLocalHost(); //实例化InetAddress类 15 InetAddress remoteAdd = InetAddress.getByName("www.baidu.com"); 16 System.out.println("本机ip:"+localAdd.getHostAddress()); //得到本地Ip地址 17 System.out.println("百度ip:"+remoteAdd.getHostAddress()); //得到远程IP地址 18 System.out.println("本机是否可达:"+localAdd.isReachable(5000)); //判断地址是否可达,同时指定超时时间 19 } 20 }
TCP和UDP
UDP:
1. 将数据源和目的封装成数据包,不需要建立连接。
2. 每个数据报的大小限制在64k内。
3. 因无连接,是不可靠协议。
4. 不需要建立连接,速度快。
TCP:
1. 建立连接,形成传输数据的通道。
2. 在连接中进行大数据量传输。
3. 通过三次握手完成连接,是可靠协议。
4. 必须建立连接,效率稍低。
注:三次握手:
第一次:我问你在么?
第二次:你回答在。
第三次:我反馈哦我知道你在。
Socket(UDP传输)
1. Socket就是为网络服务提供的一种机制。
2. 通信的两端都有Socket。
3. 网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
(一)UDP传输:
类DatagramSocket
构造:DatagramSocket()
构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port)
创建数据报套接字并将其绑定到本地主机上的指定端口。
方法:void receive(DatagramPacket p)
从此套接字接收数据报包。
void send(DatagramPacket p)
从此套接字发送数据报包。
void close()
关闭此数据报套接字。
类DatagramPacket
构造:
DatagramPacket(byte[] buf, int length)
构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
方法:
InetAddress getAddress()
返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
int getPort()
返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
1 //udp 发送端 2 import java.net.*; 3 public class UdpSend 4 { 5 public static void main(String[] args) throws Exception 6 { 7 //1. 创建udp socket,建立端点,随机端口 8 DatagramSocket ds = new DatagramSocket(); 9 //2. 确定数据,并封装成数据包 10 String str = "HelloWorld!"; 11 byte[] buf = str.getBytes(); 12 DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.101"), 3344); 13 //3. 通过DatagramSocket的send方法,将数据包dp发送出去, 14 ds.send(dp); 15 //4. 关闭资源 16 ds.close(); 17 } 18 } 1 //udp 接收端
2 import java.net.*; 3 public class UdpReceive 4 { 5 public static void main(String[] args) throws Exception 6 { 7 //1. 创建udp socket,建立断点,并指定端口 8 DatagramSocket ds = new DatagramSocket(3344); 9 10 //2. 定义数据包,用于存储数据 11 byte[] buf = new byte[1024]; 12 DatagramPacket dp = new DatagramPacket(buf,buf.length); 13 14 //3. 通过DatagramSocket中的receive方法将收到的数据存入数据包dp中 15 ds.receive(dp); //receive为阻塞式方法。 16 17 //4. 通过DatagramPacket中的方法获取数据包dp中的数据 18 String ip = dp.getAddress().getHostAddress(); 19 byte[] buff = dp.getData(); 20 int length = dp.getLength(); 21 String data = new String(buff,0,length); 22 int port = dp.getPort(); 23 System.out.println(ip+"::"+data+"::"+port); 24 25 //5. 关闭资源 26 ds.close(); 27 } 28 1 /*
2 编写一个聊天程序。 3 有收数据的部分,和发数据的部分。 4 这两部分需要同时执行。 5 那就需要用到多线程技术。 6 一个线程控制收,一个线程控制发。 7 8 因为收和发动作是不一致的,所以要定义两个run方法。 9 而且这两个方法要封装到不同的类中。 10 */ 11 12 import java.io.*; 13 import java.net.*; 14 15 class Send implements Runnable //继承Runnable 16 { 17 private DatagramSocket ds; 18 public Send(DatagramSocket ds) 19 { 20 this.ds = ds; 21 } 22 public void run() //发送端 23 { 24 try 25 { 26 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 27 String line = null; 28 while ((line=br.readLine())!=null) 29 { 30 31 byte[] buf = line.getBytes(); 32 DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 3344); 33 ds.send(dp); 34 35 if ("886".equals(line)) 36 { 37 38 break; 39 } 40 41 } 42 } 43 catch (Exception e) 44 { 45 throw new RuntimeException("发送端失败!"); 46 } 47 48 49 } 50 } 51 52 class Rec implements Runnable //继承Runnable 53 { 54 private DatagramSocket ds; 55 public Rec(DatagramSocket ds) 56 { 57 this.ds = ds; 58 } 59 public void run() //接受端 60 { 61 62 try 63 { 64 while (true) 65 { 66 byte[] buf = new byte[1024]; 67 DatagramPacket dp = new DatagramPacket(buf, buf.length); 68 ds.receive(dp); 69 70 String ip = dp.getAddress().getHostAddress(); 71 String data = new String(dp.getData(),0,dp.getLength()); 72 if ("886".equals(data)) 73 { 74 System.out.println(ip+"离开聊天室!"); 75 break; 76 } 77 78 System.out.println(ip+"::"+data); 79 } 80 81 } 82 catch (Exception e) 83 { 84 throw new RuntimeException("接收端失败!"); 85 } 86 87 } 88 } 89 90 public class ChatDemo 91 { 92 public static void main(String[] args) throws Exception 93 { 94 DatagramSocket sendSocket = new DatagramSocket(); 95 DatagramSocket recSocket = new DatagramSocket(3344); 96 new Thread(new Send(sendSocket)).start(); 97 new Thread(new Rec(recSocket)).start(); 98 99 } 100
(二)TCP传输:
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。
Socket类:
构造方法:
Socket()
通过系统默认类型的 SocketImpl 创建未连接套接字
Socket(InetAddress address, int port)
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号。
方法摘要:
void close()
关闭此套接字。
InetAddress getInetAddress()
返回套接字连接的地址。
InputStream getInputStream()
返回此套接字的输入流。
OutputStream getOutputStream()
返回此套接字的输出流。
int getPort()
返回此套接字连接到的远程端口。
void shutdownInput()
此套接字的输入流置于“流的末尾”。
void shutdownOutput()
禁用此套接字的输出流。
String toString()
将此套接字转换为 String。
ServerSocket类:
构造方法:
ServerSocket()
创建非绑定服务器套接字。
ServerSocket(int port)
创建绑定到特定端口的服务器套接字。
方法摘要:
Socket accept()
侦听并接受到此套接字的连接。
void close()
关闭此套接字。
InetAddress getInetAddress()
返回此服务器套接字的本地地址。
TCP传输流程:
(一)客户端:
1. 建立Socket服务,并建立要连接的主机和端口。
2. 获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端。
3. 获取Socket流中的输入流InputStream,获取服务端的反馈信息。
4. 关闭资源。
(二)服务端:
1. 建立ServerSocket服务,并监听一个接口。
2. 通过ServerSocket服务的accept方法,获取Socket服务对象。
3. 使用客户端对象的读取流获取客户端发送过来的数据。
4. 通过客户端对象的写入流反馈信息给客户端。
5. 关闭资源。
1 /* 2 演示tcp的传输的客户端和服务端的互访。 3 4 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。 5 6 */ 7 8 /* 9 客户端: 10 1,建立socket服务。指定要连接主机和端口。 11 2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。 12 3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。 13 4,关闭客户端资源。 14 15 */ 16 import java.io.*; 17 import java.net.*; 18 class TcpClient2 19 { 20 public static void main(String[] args)throws Exception 21 { 22 Socket s = new Socket("192.168.1.254",10004); 23 24 OutputStream out = s.getOutputStream(); 25 26 out.write("服务端,你好".getBytes()); 27 28 29 InputStream in = s.getInputStream(); 30 31 byte[] buf = new byte[1024]; 32 33 int len = in.read(buf); 34 35 System.out.println(new String(buf,0,len)); 36 37 s.close(); 38 } 39 } 40 41 42 class TcpServer2 43 { 44 public static void main(String[] args) throws Exception 45 { 46 ServerSocket ss = new ServerSocket(10004); 47 48 Socket s = ss.accept(); 49 50 String ip = s.getInetAddress().getHostAddress(); 51 System.out.println(ip+"....connected"); 52 InputStream in = s.getInputStream(); 53 54 byte[] buf = new byte[1024]; 55 56 int len = in.read(buf); 57 58 System.out.println(new String(buf,0,len)); 59 60 61 OutputStream out = s.getOutputStream(); 62 63 64 Thread.sleep(10000); 65 out.write("哥们收到,你也好".getBytes()); 66 67 s.close(); 68 69 ss.close(); 70 } 71 }
TCP练习:
1 /* 2 需求:建立一个文本转换服务器。 3 客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。 4 而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。 5 分析: 6 客户端: 7 既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。 8 源:键盘录入。 9 目的:网络设备,网络输出流。 10 而且操作的是文本数据。可以选择字符流。 11 步骤 12 1,建立服务。 13 2,获取键盘录入。 14 3,将数据发给服务端。 15 4,后去服务端返回的大写数据。 16 5,结束,关资源。 17 都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。 18 */ 19 import java.io.*; 20 import java.net.*; 21 class TransClient 22 { 23 public static void main(String[] args) throws Exception 24 { 25 Socket s = new Socket("192.168.1.254",10005); 26 //定义读取键盘数据的流对象。 27 BufferedReader bufr = 28 new BufferedReader(new InputStreamReader(System.in)); 29 //定义目的,将数据写入到socket输出流。发给服务端。 30 //BufferedWriter bufOut = 31 //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 32 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 33 34 //定义一个socket读取流,读取服务端返回的大写信息。 35 BufferedReader bufIn = 36 new BufferedReader(new InputStreamReader(s.getInputStream())); 37 38 String line = null; 39 40 while((line=bufr.readLine())!=null) 41 { 42 if("over".equals(line)) 43 break; 44 45 out.println(line); 46 // bufOut.write(line); 47 // bufOut.newLine(); 48 // bufOut.flush(); 49 50 String str =bufIn.readLine(); 51 System.out.println("server:"+str); 52 53 } 54 55 bufr.close(); 56 s.close(); 57 58 59 } 60 } 61 /* 62 服务端: 63 源:socket读取流。 64 目的:socket输出流。 65 都是文本,装饰。 66 */ 67 class TransServer 68 { 69 public static void main(String[] args) throws Exception 70 { 71 ServerSocket ss = new ServerSocket(10005); 72 73 Socket s = ss.accept(); 74 String ip = s.getInetAddress().getHostAddress(); 75 System.out.println(ip+"....connected"); 76 77 //读取socket读取流中的数据。 78 BufferedReader bufIn = 79 new BufferedReader(new InputStreamReader(s.getInputStream())); 80 81 //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。 82 //BufferedWriter bufOut = 83 //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 84 85 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 86 87 String line = null; 88 while((line=bufIn.readLine())!=null) 89 { 90 91 System.out.println(line); 92 93 out.println(line.toUpperCase()); 94 // bufOut.write(line.toUpperCase()); 95 // bufOut.newLine(); 96 // bufOut.flush(); 97 } 98 99 s.close(); 100 ss.close(); 101 102 } 103 } 104 /*该例子出现的问题。 105 现象:客户端和服务端都在莫名的等待。 106 为什么呢? 107 因为客户端和服务端都有阻塞式方法。这些方法么没有读到结束标记。那么就一直等 108 而导致两端,都在等待。 109 */
---------------------- android培训、java培训、期待与您交流! ----------------------