1.1、网络编程
网络通讯包含三个要素:IP地址、端口、传输协议。
基本使用:首先找到对方ip地址,然后发送数据到对方指定的应用程序上,通过端口对应用程序进行数组标识,再定义通信规则(协议)。
端口:0 - 65535称之为逻辑端口,其中0 - 1024一般被系统所调用。
通信协议:TCP / IP (广域网和局域网通用)
网络参考模型
注:我们目前是在传输层,等将来学习javaweb是在应用层。具体参考图。
1、UDP
UDP将数据源和目的地封装在数据包中,不需要建立连接,每个数据包大小限制在64k内,由于面向无连接,所以是不可靠的协议,
但是由此它的执行速度和效率高。
Socket就是为网络服务提供的一种机制,通信的两端都需要有Socket,数据在两个Socket间通过I/O传输。
UDP传输
- DatagramSocket 与 DatagramPacket 。
- 建立发送端,接收端。
- 建立数据包。
- 调用Socket的发送接收方法。
- 关闭Soket。
发送端与接收端是两个独立的运行程序。
注:DatagramPacket:它是发送数据的包,构造方法有很多,既能接收也能发送。凡是带地址的都是发送的。
UDP接收与发送:
发送端:
public class UdpSend { public void send(){ try { //1.创建udp服务,通过DatagramSocket对象。 DatagramSocket ds = new DatagramSocket(8888); //2.确定数据,并封装成数据包。 byte[] buf = "发送UDP数据!".getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.105"),10001); //3.通过soket服务,将已有的数据包发送出去。通过send方法。 ds.send(dp); //4.关闭资源 ds.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args){ UdpSend client = new UdpSend(); client.send(); } }
接收端:
public class UdpReceiver { public void receiver(){ try { //1.创建udp socket服务,建立端点。 DatagramSocket ds = new DatagramSocket(10001); //2.定义数据包,用于存储数据。 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); //3.通过服务的receive方法将收到数据存入数据包中,阻塞式方法 ds.receive(dp); //4.通过数据包的方法获取其中的数据。 String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(ip+"::"+data+"::"+port); //5.关闭资源 ds.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args){ UdpReceiver server = new UdpReceiver(); server.receiver(); } }
运行结果:
总结:UDP其实是通过Datagramsocket在接收和发送两端建立通信,再对数据进行封包,发送给接收端来解包。(没有服务端和客户端)
2、TCP
TCP建立连接后,形成传输数据的通道,可以进行大数据量传输,通过三次握手来完成连接,是可靠的协议,效率略低。
a) 客户端给服务端发送信息:
客户端:创建客户端Socket,并指定IP和端口。通过查阅socket对象,发现该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输(包含输出流和输入流)。
需求:给服务端发送一个文本数据。
1.创建Socket服务。并指定要连接的主机和端口。
//创建客户端的Socket服务,指定目的主机和端口。 Socket s = new Socket("192.168.14.166",10003); //为了发送数据,应该获取socket流中的输出流来。 OutputStream out = s.getOutputStream(); out.write("tcp,哥们来了!".getBytes()); s.close();
服务端:
//建立服务端socket服务,并监听一个端口。 ServerSocket ss = new ServerSocket(10003); //通过accep方法获取连接过来的客户端对象。 Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connect.."); //获取客户端发送过来的数据,那么要使用客户端对象的读取流读取数据。 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close();//关闭客户端。 ss.close();//关闭服务端。
b) 服务端反馈客户端信息:
需求:对上面的实例进行增强,客户给服务端发送数据,服务端收到后,会反馈信息给客户端来输出。
//通过输出流给服务端发送数据。 Socket s = new Socket("192.168.14.166",10004); OutputStream out = s.getOutputStream(); out.write("服务端,你好".getBytes()); //获取服务端反馈回来的输入流,并打印。 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close();
服务端:
ServerSocket ss = new ServerSocket(10004); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connect...."); //服务端收到数据后先读取一次。 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); //服务端给客户端反馈信息。 OutputStream out = s.getOutputStream(); out.write("收到,客户端你也好".getBytes()); s.close(); ss.close();
运行结果:
Server:
Client: