网络通信——Java篇

一、网络编程三要素

  • IP地址:唯一识别计算机、设备
  • 端口:唯一识别计算机中的应用程序,取值范围是0~65535,且普通应用程序需使用1024以上的端口号,因为0~1023用于一些知名的网络服务和系统应用
  • 协议:位于同一个网络中计算机在进行连接和通信时需要遵守一定的规则,这些规则被称为网络通信协议,他对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。常见的协议有UDP协议和TCP协议

二、TCP与UDP协议

  • UDP协议:用户数据报协议

    UDP是面向无连接的通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机想另外一台计算机发送数据时,发送端不会确认接收端是否存在,直接发送数据,同理,接收端在收到数据时,也不会向发送端反馈是否收到数据。

    由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通(不重要的)数据的传输。

    例如视频会议通常采用UDP协议,因为这种情况即时偶尔丢失了一些数据包,也不会对整个结果产生太大影响。但是使用UDP协议传输数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时,不建议使用UDP协议。

  • TCP协议:传输控制协议
        TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端需建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务器端发出连接请求,且每次连接的创建都需要经过“三次握手”。
        完成三次握手,并建立连接后,客户端和服务端就可以开始传输数据了。由于这种面相连接的特性,TCP协议可以保证数据传输的安全,所以应用十分广泛,如上传文件、下载文件、浏览网页等。
        三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
  • 第一次握手:客户端向服务器发送连接请求,等待服务器确认
  • 第二次握手:服务器收到请求,并向客户端回送一个响应,通知客户端收到了请求
  • 第三次握手:客户端向服务端发送确认信息,以确认连接

三、InetAddress类

方便我们对IP地址的获取和操作,此类表示Internet协议(IP)地址。
  • static InetAddress getByName(String
    host):确定主机名称host的IP地址。主机名称可以是机器名称,也可以是IP地址(此为静态方法,采用类名调用)
  • String getHostName():获取此IP地址的主机名
  • String getHostAddress():返回文本显示中的IP地址字符串
InetAddress address = InetAddress.getByName("192.168.100.162");
System.out.println(address.getHostAddress());
System.out.println(address.getHostName());

四、UDP编程

  • UDP发送数据(客户端)步骤:
    ①创建发送端的DatagramSocket对象
    ②创建数据包DatagramPacket,指定数据、长度、ip地址、端口号,即指定要发送到哪
    ③调用DatagramSocket对象的send方法发送数据
    ④关闭发送端
    实现如下:
public static void main(String[] args) throws Exception {
	DatagramSocket ds = new DatagramSocket();
	String str = new String("Hello World!");
	DatagramPacket dp = new DatagramPacket(str.getBytes(), str.getBytes()
.length(), InetAddress.getByName("192.168.100.162"), 8090);
	ds.send(dp);
	ds.close();
}
  • UDP接收数据(服务端)步骤:
    ①创建接收端的DatagramSocket对象,并指定端口
    ②创建一个数据包,用于接收数据
    ③调用DatagramSocket的receive方法接收数据
    ④解析数据包,打印结果
    ⑤关闭接收端
    实现如下:
public static void main(String[] args) throws Exception {
	DatagramSocket ds = new DatagramSocket(8090);
	byte[] bytes = new byte[1024];
	DatagramPacket data = new DatagramPacket(bytes, bytes.length);
	ds.receive(data);
	byte[] newbys = data.getData();
	int length = data.getLength();
	//将有用的数据保留下来,长度为data.getLength()
	String str = new String(newbys, 0, length);
	System.out.println(str);
	ds.close();
}

五、TCP编程

  • TCP发送数据(客户端)步骤:
    ①创建客户端的Socket对象,并指定IP和端口,即指定要发送到哪
    ②通过Socket对象获取输出流,输出数据
    ③释放资源
public static void main(String[] args) throws Exception {
	Socket socket = new Socket(InetAddress.getByName("192.168.100.180"), 9099);
	OutputStream out = socket.getOutputStream();
	BufferedOutputStream bos = new BufferedOutputStream(out);
	bos.write("你好,我是客户端,我发送的数据是10086".getBytes());
	bos.flush();
	socket.close();
}
  • TCP接收数据(服务端)步骤:
    ①创建服务器端的ServerSocket对象,并绑定监听端口
    ②调用accept方法监听客户端的连接,并获取Socket对象
    ③通过Socket对象获取输入流,读数据
    ④释放资源
public static void main(String[] args) throws Exception {
	ServerSocket serverSocket = new ServerSocket(9099);
	Socket socket = serverSocket.accept();
	InputStream in = socket.getInputStream();
	BufferedInputStream bis = new BufferedInputStream(in);
	byte[] bys = new byte[1024];
	int len = 0;
	while((len = bis.read(bys))!=-1) {
		System.out.println("客户端发送的数据是:" + new String(bys, 0, len));
	}
	serverSocket.close();
}

六、多线程实现TCP通信

    为什么要用多线程,是因为服务器一般是一直启动的,不会关闭,因此他要一直监听客户端,所以采用多线程来实现为每一个客户端建立一个专线连接,即每有一个客户端请求,服务器就创建一个线程与之通信。

  • 服务器线程,监听多个客户端
public class ServerThread implements Runnable{
	private Socket socket;
	
	public ServerThread(Socket socket) {
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\IO\\ServerFile.txt"));
			String line;
			while((line = br.readLine())!=null) {
				System.out.println(line);
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
			OutputStream out = socket.getOutputStream();
			out.write("我是服务器,已成功接收数据".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • 服务器端
public class Server {
	public static void main(String[] args) throws Exception {
		ServerSocket serverSocket = new ServerSocket(9099);
		while(true) {
			Socket socket = serverSocket.accept();
			new Thread(new ServerThread(socket)).start();
		}
	}
}
  • 客户端
public class Client {
	public static void main(String[] args) throws Exception {
		Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9099);
		BufferedReader br = new BufferedReader(new FileReader("E:\\IO\\静夜思.txt"));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		String line = "";
		while((line = br.readLine())!=null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		socket.shutdownOutput();
	
		InputStream in = socket.getInputStream();
		byte[] bys = new byte[1024];
		int len = in.read(bys);
		System.out.println("我是客户端,服务器的反馈为:" + new String(bys, 0, len));
		socket.close();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sadness°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值