1、网络编程三要素:
- 地址:定位电脑
本地回路地址:127.0.0.1
广播地址:255.255.255.255 - 端口号:定位电脑中的程序
o~65525
尽量使用1024以上的 - 协议:数据交换的规则/标准
UDP: 面向无连接,数据不安全,速度快,不区分客户端与服务端
TCP:面向连接(三次握手),数据安全,速度略低,分为客户端和服务端
(三次握手:客户端先向服务端发起请求,服务端响应请求,传输数据)
socket = IP地址+端口号
- 通信的两端都有socket
- 网络通信就是socket之间的通信
- 数据在两个socket之间通过IO流传输
- socket在应用程序中创建,通过绑定机制与驱动程序建立关系,告诉自己所对应的IP和port
2、UDP传输:
UDP传输其实就两个类:
- DatagramSocket;建立端口,传输数据 send/receive
- DatagramPacket;打包数据(数据要转换成字节数组传输)
代码实例:(运行程序的时候要先将接受端打开再发送)
这里用while循环和if语句使得输入端能够持续发送,接收端能够持续接受(接收端就不需要close了)
UDPsocket_send:
package SocketCollection;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/*
* DatagramSocket 建立港口
* DatagramPacket 资料包
*/
public class UDPsocket_send {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要传输的内容:");
DatagramSocket socket = new DatagramSocket();
while (true) {
String str = sc.nextLine();
if (str.equals("quit")) {
break;
}
byte[] arr = str.getBytes();
DatagramPacket packet =
new DatagramPacket(arr, arr.length, InetAddress.getByName("127.0.0.1"), 6770);
socket.send(packet);
}
socket.close();
}
}
UDPsocket_receive:
package SocketCollection;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*
* DatagramSocket 建立港口
* DatagramPacket 资料包
*/
public class UDPsocket_receive {
public static void main(String[] args) throws IOException {
byte[] arr = new byte[1024];
DatagramSocket socket = new DatagramSocket(6770);
DatagramPacket packet = new DatagramPacket(arr, 1024); // arr是用于保存数据的缓存区,lenth是要读取的长度,小于等于arr.lenth
while (true) {
socket.receive(packet); // socket接受字节包并存放在packet中
byte[] parr = packet.getData();
int lenth = packet.getLength();// 这个资料包的实际大小
String str = new String(parr, 0, lenth);// 接受并转为string对象输出
System.out.println(str);
}
}
}
效果图(看见console右上角的两个标志的下拉菜单了么,可以创建一个新的控制台pin起来,选择显示的程序,同时开两个console):
3、多线程UDP传输:
改进一下,用多线程让上面两个程序在同一个控制台下输出
思路:
- Receive和Send类继承Thread方法
- 重写run方法,将原来的输入和输出写在run方法里(这里alt+shift+z 直接把run下面整个程序try-catch,不能throws!)
- 主程序创建Receive和Send类.start()
- 这里的输出我再加上ip地址和端口号
代码如下
package SocketCollection;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class UDPwithmultiThread {
public static void main(String[] args) {
new Receive().start();
new Send().start();
}
}
class Receive extends Thread {
public void run() {
try {
byte[] arr = new byte[1024];
DatagramSocket socket = new DatagramSocket(6787);
DatagramPacket packet = new DatagramPacket(arr, 1024); // arr是用于保存数据的缓存区,lenth是要读取的长度,小于等于arr.lenth
while (true) {
socket.receive(packet); // socket接受字节包并存放在packet中
byte[] parr = packet.getData();
int lenth = packet.getLength();// 这个资料包的实际大小
String str = new String(parr, 0, lenth);// 接受并转为string对象输出
String ip = packet.getAddress().getHostAddress();//获取ip地址
int pot = packet.getPort();
System.out.println(ip + ":" + pot + " " + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Send extends Thread {
public void run() {
try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要传输的内容:");
DatagramSocket socket = new DatagramSocket();
while (true) {
String str = sc.nextLine();
if (str.equals("quit")) {
break;
}
byte[] arr = str.getBytes();
DatagramPacket packet = new DatagramPacket(arr, arr.length, InetAddress.getByName("127.0.0.1"), 6787);
socket.send(packet);
}
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
效果如图:
4、三次握手&四次挥手
参考文章:TCP三次握手和四次挥手过程
能画出来是最基础的(具体看上面的博文,写的很好):