网络编程
1、IP地址和端口号
通过IP地址可以连接到指定计算机,但如果想访问目标计算机中的某个应用程序,还需要指定端口号。在计算机中,不同的应用程序是通过端口号区分的。端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535(2的16次方为65536),其中,0~1023之间的端口号是用于一些知名的网络服务和应用,用户的普通应用程序需要使用1024以上的端口号,从而避免端口号被另外一个应用或服务所占用。
2、使用UDP协议实现通信功能
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失有一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
DatagramPacket数据包的作用就如同“集装箱”,可以将发送端或者接收端的数据封装起来。然而运输货物只有“集装箱”是不够的,还需要有码头。DatagramPacket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包。
发送端于接收端交互图解
发送端
package com.zy.demo2; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; public class UDPSend { public static void main(String[] args) throws Exception { //1创建码头 DatagramSocket datagramSocket = new DatagramSocket(); //2创建集装箱 String data="中国食用油"; byte[] bytes = data.getBytes(); //3发送数据 //根据名字获取主机(机器互联) InetAddress byName = InetAddress.getByName("192.168.219.61");//getByName("127.0.0.1")也可以写ip,不一定非得是主机名 DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, byName, 9999); datagramSocket.send(datagramPacket); //4释放资源 datagramSocket.close(); } }
接收端
package com.zy.demo2; import java.io.File; import java.io.FileOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPReceive { public static void main(String[] args) throws Exception { //1创建码头 DatagramSocket datagramSocket = new DatagramSocket(9999);//双方约定的 //2创建集装箱 byte b[]=new byte[1024];//空的字节数组 DatagramPacket datagramPacket = new DatagramPacket(b, b.length); //3收货 datagramSocket.receive(datagramPacket);//线程阻塞!!!(没收到时) //4查看货物 System.out.println(new String(b)); //5释放资源 datagramSocket.close(); } }
先运行接收端,虚拟灯一直亮着等待发送端发送数据
再运行发送端,然后回到接收端console
2、使用TCP实现服务与客户端通信
TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。
区别在于,UDP中只有发送端和接收端,不区分客户端和服务端,计算机之间可以任意地发送数据。而TCP通信是严格区分客户端和服务端的,在通信时。必须先由客户端去连接服务端才能实现通信,服务端不可以主动连接客户端,并且服务端程序需要事先启动,等待客户端的连接。
通信时。首先创建代表服务端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务端发送连接请求,服务端响应请求,两者建立连接开始通信。
服务端程序
package LESSON13; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class TCPserver { /** 使用TCP接收数据 创建接收端Socket对象 监听(阻塞) 获取输入流对象 获取数据 输出数据 释放资源 ServerSocket此类实现服务器套接字。 ServerSocket(int port) 创建绑定到特定端口的服务器套接字 * @throws Exception */ public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(9999);// 创建接收端Socket对象 Socket s = server.accept();//监听(阻塞)等待连接 //通信 InputStream in=s.getInputStream();// 获取输入流对象(接收数据) byte b[]=new byte[1024]; in.read(b);//接收客户端发来的信息 OutputStream out=s.getOutputStream();//获取输出流对象(发送数据) out.write("你好,我是服务器".getBytes());//向客户端发送信息 // InetAddress getInetAddress() 返回套接字连接的地址。 InetAddress address = s.getInetAddress(); System.out.println("client"+"\t"+address.getHostAddress()); System.out.println(new String(b).trim()); in.close(); s.close(); //ss.close(); } }
客户端程序
package LESSON13; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class TCPclient { /** 使用TCP发送数据 创建发送端Socket对象(创建连接) 获取输出流对象 发送数据 释放资源 Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 Exception in thread "main" java.net.ConnectException: Connection refused: connect * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub InetAddress address=InetAddress.getByName("localhost");//获取本地IP地址 Socket client=new Socket(address, 9999);//创建发送端Socket对象(创建连接) //通信 OutputStream out=client.getOutputStream();//获取输出流对象(发送数据) out.write("服务器你好,我是客户端".getBytes());//发送数据 InputStream in=client.getInputStream();//获取输入流睡醒(接收数据) byte b[]=new byte[1024]; in.read(b);//接收服务器发送来的信息 System.out.println(new String(b).trim()); out.close(); client.close(); } }
先运行服务端,再运行客户端