1 了解了网络通讯中的三个要素: IP地址、端口号、通讯协议
* Java中有一个类就可以来表示IP地址
*
* InetAddress: 此类表示互联网协议(IP)地址.
*
* ipconfig: 可以获取当前计算机的网卡 和 IP地址
*
* */
public class A_netAddressDemo { public static void main(String[] args) throws UnknownHostException { //static InetAddress getByName(String host) : 在给定主机名的情况下确定主机的 IP 地址。 InetAddress address = InetAddress.getByName("172.24.124.93"); // ip地址是唯一的 InetAddress address1 = InetAddress.getByName("LAPTOP-R9G4F3MU"); // ip地址是唯一的 System.out.println(address); System.out.println(address1); System.out.println("-------------------------"); String hostAddress = address.getHostAddress(); // 172.24.124.93 返回IP地址 String hostName = address.getHostName(); // 返回主机名LAPTOP-R9G4F3MU System.out.println(hostName); System.out.println(hostAddress); } }
2 使用UDP协议接收数据
创建接收端Socket对象
创建包对象(DatagramPacket)
接收数据(receive)
解析数据
输出数据
释放资源//DatagramPacket:(此类表示数据报包。)用来接收UDP协议传过来的数据的
快捷键:alt+shift+r修改文件名字
public class B_ReceiveDemo { public static void main(String[] args) throws IOException { //创建接收端Socket对象 DatagramSocket ds = new DatagramSocket(8888); //接收数据 //DatagramPacket(byte[] buf, int length) byte[] bys = new byte[1024]; DatagramPacket dp = new DatagramPacket(bys,bys.length);//存入字节数组了,存入的长度为1024,所以最多只能输出1024个字节,多了的会自动戒掉! System.out.println(1); ds.receive(dp);//(从此套接字接收数据报包)阻塞,收到数据后才会放行! System.out.println(2); //解析数据 //InetAddress getAddress() : 获取发送端的IP对象 InetAddress address = dp.getAddress(); //byte[] getData() :获取接收到的数据,也可以直接使用创建包对象时的数组 byte[] data = dp.getData(); //int getLength() :获取具体收到数据的长度 int length = dp.getLength(); //输出数据 System.out.println("sender ---> " + address.getHostAddress()); System.out.println(new String(data,0,length)); //字节数组转成字符串 System.out.println(new String(bys,0,length)); //字节数组转成字符串 //释放资源 ds.close(); } }
2 使用UDP协议发送数据
1.创建发送端Socket对象
2.创建数据并打包
3.发送数据
4.释放资源
*
* DatagramSocket:(此类表示用来发送和接收数据报包的套接字)此类表示用来发送和接收数据,基于UDP协议的
*
* DatagramSocket() :创建Socket对象并随机分配端口号
* DatagramSocket(int port) :创建Socket对象并指定端口号
*
*
* ctrl+1快捷键:补全代码前半段
*/
public class B_SendDemo { public static void main(String[] args) throws IOException { //创建发送端Socket对象 DatagramSocket ds = new DatagramSocket(); //创建数据并打包 /* * DatagramPacket :此类表示数据报包 * byte[] buf:数据byte[] * int length:传输字节的长度 * InetAddress address:设备的地址 ip * int port:进程的地址 端口号 DatagramPacket(byte[] buf, int length, InetAddress address, int port) */ String s = "hello udp,im comming!"; byte[] bys = s.getBytes();//字符串转成字符数组 int length = bys.length; InetAddress address = InetAddress.getByName("172.24.124.93");//发送给当前设备 或者使用主机名:LAPTOP-R9G4F3MU int port = 8888; //打包 DatagramPacket dp = new DatagramPacket(bys,length,address,port); //发送数据 ds.send(dp); //释放资源 ds.close(); } }
3 重复第2点
package day45_day46; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class B_ReceiveDemo2 { public static void main(String[] args) throws Exception { //1.创建接收端Socket对象 DatagramSocket ds = new DatagramSocket(9999); //2.创建包对象 byte[]bys = new byte[1024]; // 构造 DatagramPacket,用来接收长度为 length 的数据包。 DatagramPacket pd = new DatagramPacket(bys,bys.length); //3.接收数据 ds.receive(pd); //4.解析数据 //4.1获取发送端IP对象 InetAddress address = pd.getAddress(); //4.2获取数据 byte[] data = pd.getData(); //4.3获取数据的长度 int length = pd.getLength(); //5.输出数据 System.out.println("接收到的数据:"+address.getHostName()); System.out.println(new String(data,0,length)); //6.释放资源 ds.close(); } }
package day45_day46; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /* * UDP协议收发数据的注意事项: * A: 端口号错误: 数据可以正常发出,但是接收端收不到数据 * B:Exception in thread "main" java.net.BindException: Address already in use: Cannot bind * 启动了两个接收端,端口号第一个接收端已经占用了,第二个接收端再去使用就报错了 * * * 发送端和接收端是有个数据包的! * */ public class B_SendDemo2 { public static void main(String[] args) throws Exception { //1.创建发送端的Socket对象 DatagramSocket ds = new DatagramSocket(); //2.创建包对象 byte[] bytes = "Hello,World! UDP....".getBytes(); // 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 DatagramPacket dp = new DatagramPacket(bytes,bytes.length,InetAddress.getByName("PS20190620DZMJ"),9999); //3.发送数据 ds.send(dp); //4.释放资源 ds.close(); } }
4 使用TCP协议发送数据
创建发送端Socket对象(创建连接)
获取输出流对象
发送数据
释放资源
Socket(InetAddress address, int port)
Exception in thread "main" java.net.ConnectException: Connection refused: connect 没有连接就会报错客户端:发送数据(设置端口)
public class C_ClientDemo { public static void main(String[] args) throws IOException { //创建发送端Socket对象(创建连接) Socket s = new Socket(InetAddress.getByName("LAPTOP-R9G4F3MU"),10086); //创建一个流套接字并将其连接到指定 IP 地址的指定端口号 //通过Socket对象-->获取输出流对象 OutputStream os = s.getOutputStream(); //发送数据 String str = "hello tcp,im comming!!!"; os.write(str.getBytes()); //释放资源 //os.close(); s.close(); } }
4 使用TCP协议接收数据
创建接收端Socket对象
监听(阻塞)
获取输入流对象
获取数据
输出数据
释放资源
ServerSocket:接收端
Socket:服务端
ServerSocket(int port) 对应端口
Socket accept() 阻塞,等待接收
服务端:接收数据(需要端口)
服务端和客户端之间是有个流的
public class C_ServerDemo { public static void main(String[] args) throws IOException { //创建接收端Socket对象 ServerSocket ss = new ServerSocket(10086); //监听(阻塞),就是一直等着接收功能 Socket s = ss.accept(); //通过Socket对象获取输入流对象 InputStream is = s.getInputStream(); //获取数据 byte[] bys = new byte[1024]; int len;//用于存储读到的字节个数 len = is.read(bys);//读进字节数组 //输出数据 InetAddress address = s.getInetAddress(); System.out.println("client ---> " + address.getHostName()); System.out.println(new String(bys,0,len)); //释放资源 s.close(); //ss.close(); } }
5 通过TCP
需求:使用TCP协议发送数据,并将接收到的数据转换成大写返回(关键是他们之间可以相互传来传去!!)
客户端发出数据
服务端接收数据
服务端转换数据
服务端发出数据
客户端接收数据
*/客户端:
public class C_ClientDemo2 { public static void main(String[] args) throws IOException { //创建客户端Socket对象 Socket s = new Socket(InetAddress.getByName("LAPTOP-R9G4F3MU"),10010); //获取输出流对象 OutputStream os = s.getOutputStream(); //发出数据 os.write("tcp,im comming again!!!".getBytes()); //获取输入流对象 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len;//用于存储读取到的字节个数 //接收数据 len = is.read(bys); //输出数据 System.out.println("step2:"+new String(bys,0,len)); //释放资源 s.close(); } }
服务端:
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class C_ServerDemo2 { public static void main(String[] args) throws IOException { //创建服务端Socket对象 ServerSocket ss = new ServerSocket(10010); //监听 Socket s = ss.accept(); //获取输入流对象 InputStream is = s.getInputStream(); //获取数据 byte[] bys = new byte[1024]; int len;//用于存储读取到的字节个数 len = is.read(bys); String str = new String(bys,0,len); //输出数据 System.out.println("step1:"+str); //转换数据 String upperStr = str.toUpperCase(); //就是大写方法! //获取输出流对象 OutputStream os = s.getOutputStream(); //返回数据(发出数据) os.write(upperStr.getBytes()); //释放资源 s.close(); // ss.close();//服务端一般不关闭 } }
6 通过TCP
/*
* 模拟用户登录(跟第五点有点像,都是传来传去)
*
*/客户端:
package day45_day46; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; /* * 模拟用户登录 * */ public class D_ClientTest { public static void main(String[] args) throws IOException { //创建客户端Socket对象 Socket s = new Socket("LAPTOP-R9G4F3MU",8888); //获取用户名和密码 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //缓冲流与标准输入输出流 System.out.println("请输入用户名:"); String username = br.readLine(); System.out.println("请输入密码:"); String password = br.readLine(); //获取输出流对象 // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); //表示追加,很方便,写完一行就换行,与后面的服务端接收一次读取一行对应上了 // //写出数据 // bw.write(username); // bw.newLine(); // bw.flush(); // bw.write(password); // bw.newLine(); // bw.flush(); out.println(username); out.println(password); //获取输入流对象 BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream())); //获取服务器返回的数据 String result = serverBr.readLine(); System.out.println(result); //释放资源 // bw.close(); s.close(); } }
服务端:
package day45_day46; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class D_ServerTest { public static void main(String[] args) throws IOException { //创建服务器端Socket对象 ServerSocket ss = new ServerSocket(8888); //监听 Socket s = ss.accept(); //获取输入流对象 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); //获取用户名和密码 String username = br.readLine(); String password = br.readLine(); //判断用户名和密码是否正确 boolean flag = false; if("user".equals(username) && "123456".equals(password)) { flag = true; } //获取输出流对象 PrintWriter out = new PrintWriter(s.getOutputStream(),true); //返回判断信息 if(flag) { out.println("登陆成功"); } else { out.println("登陆失败"); } //释放资源 s.close(); //ss.close();//服务器一般不关闭 } }