Java基础---网络编程

 

网络编程

一、网络编程的概述

1、网络编程就是实现网络互连的不同计算机上运行的程序的数据交换。

2、计算机要进行信息传输就需要有一定的规则,计算机网络通信的这些规则是网络模型研究的问题,一般有两种网络模型:OSIOpen SystemInterconnection开放系统互连)参考模型TCP/IP参考模型,如下图:

 

3.网络编程一般针对网络层和传输层进行。网络层主要将从下层接收到的数据进行IP地址的封装与解封装,在这一层工作的设备是路由器,常把这一层的数据叫做数据包; 传输层定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据,如上传下载),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。传输层主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组,常常把这一层数据叫做段。

二、网络通信三要素

1、IP地址:InetAddress,网络中设备的标识,不易记忆,可用主机名;

                  要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。

2、 端口号: 用于标识进程的逻辑地址,不同进程的标识;
                     网络程序都会至少有一个逻辑端口用于标识进程的逻辑地址,有效端口号为 0~65535,其中0~1024系统使用或保留端口。

3、传输协议:即通讯的规则,常见协议:TCP,UDP。

                        UDP:将数据源和目的封装成数据包中,不需要建立连接,每个数据报的大小在限制在64k,因无连接,是不可靠协议,不需要建立连接,速度快

                        TCP:建立连接,形成传输数据的通道,在连接中进行大数据量传输,通过三次握手完成连接,是可靠协议,必须建立连接,效率会稍低

三、网络编程常用类

(1)InetAddress类:

       常用功能:a.获取任意主机:getByName;b.获取主机名:getHostName;c.获取主机Ip地址:getHostAddress;

(2)Socket类:

       Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字;

       Socket原理机制:通信的两端都有Socket;网络通信其实就是Socket间的通信数据在两个Socket间通过IO传输。

Socket机制图解

 

(3)UDP相关类:DatagramSocket与DatagramPacket;

         建立发送端,接收端。DatagramSocket

         建立数据包。DatagramPacket

         调用Socket的发送接收方法。send()和receive()方法;receive()方法阻塞是方法.没数据就等着

         关闭Socket。close()方法;

(4)TCP相关类:Socket和ServerSocket;

          建立客户端(Socket)和服务器端(ServerSocket);

          建立连接后,通过Socket中的IO流进行数据的传输。getOutputStream()和getInputStream()方法

          关闭socket。close()方法

三、网络编程的应用

1、UDP传输(模拟收发短信息)

     发送端思路:

            1:建立udpsocket服务;

            2:将要发送的数据封装成数据包;

            3:通过udpsocket服务,将数据包发送出;

            4:关闭资源。

【案例——发送端】

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * 数据来自于键盘录入
 * 键盘录入数据要自己控制录入结束。
 */
public class SendDemo {
	public static void main(String[] args) throws IOException {
		// 创建发送端的Socket对象
		DatagramSocket ds = new DatagramSocket();

		// 封装键盘录入数据
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line = null;
		while ((line = br.readLine()) != null) {
			if ("886".equals(line)) {
				break;
			}

			// 创建数据并打包
			byte[] bys = line.getBytes();
			
			/* DatagramPacket dp = new DatagramPacket(bys, bys.length,
			   InetAddress.getByName("192.168.1.108"), 10086);*/
			DatagramPacket dp = new DatagramPacket(bys, bys.length,
					InetAddress.getByName("192.168.1.108"), 10086);

			// 发送数据
			ds.send(dp);
		}

		// 释放资源
		ds.close();
	}
}

     接收端思路:

            1:建立udpsocket服务;

            2:通过receive方法接收数据;

            3:将收到的数据存储到数据包对象中;

            4:通过数据包对象的功能来完成对接收到数据进行解析;
            5: 可以对资源进行关闭。(一般不关闭,因为关闭后接收不到数据了)

【案例——接收端】

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * 本程序能看到:多次启动接收端会出现端口被占用异常
 * 		java.net.BindException: Address already in use: Cannot bind
 */
public class ReceiveDemo {
	public static void main(String[] args) throws IOException {
		// 创建接收端的Socket对象
		DatagramSocket ds = new DatagramSocket(10086);

		while (true) {
			// 创建一个包裹
			byte[] bys = new byte[1024];
			DatagramPacket dp = new DatagramPacket(bys, bys.length);

			// 接收数据
			ds.receive(dp);

			// 解析数据
			String ip = dp.getAddress().getHostAddress();
			String s = new String(dp.getData(), 0, dp.getLength());
			System.out.println("from " + ip + " data is : " + s);
		}

		// 释放资源
		// 接收端应该一直开着等待接收数据,是不需要关闭
		// ds.close();
	}
}

2、TCP传输(模拟上传文件)

      客户端思路:

             1:建立客户端的Socket服务,并明确要连接的服务器;

             2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入,该通道称为Socket,Socket流中既有读取流,也有写入流;

             3:通过Socket对象的方法,可以获取这两个流;

             4:通过流的对象可以对数据进行传输;

            5:如果传输数据完毕,关闭资源。

【案例——客户端】

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class UploadClient {
	public static void main(String[] args) throws IOException {
		// 创建客户端Socket对象
		Socket s = new Socket("192.168.1.108", 10010);

		// 封装文本文件
		BufferedReader br = new BufferedReader(new FileReader(
				new File("F:\\答辩PPT.ppt")));
		// 封装通道内流
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				s.getOutputStream()));

		String line = null;
		while ((line = br.readLine()) != null) { // 阻塞
			bw.write(line);
			bw.newLine();
			bw.flush();
		}

		// Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
		s.shutdownOutput();

		// 接收反馈
		BufferedReader brClient = new BufferedReader(new InputStreamReader(
				s.getInputStream()));
		String client = brClient.readLine(); // 阻塞
		System.out.println(client);

		// 释放资源
		br.close();
		s.close();
	}
}

【案例——服务器】

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {
	public static void main(String[] args) throws IOException {
		// 创建服务器端的Socket对象
		ServerSocket ss = new ServerSocket(10010);

		// 监听客户端连接
		Socket s = ss.accept();// 阻塞

		// 封装通道内的流
		BufferedReader br = new BufferedReader(new InputStreamReader(
				s.getInputStream()));
		// 封装文本文件
		BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
				"F:\\copy答辩.ppt")));

		String line = null;
		while ((line = br.readLine()) != null) { // 阻塞
			bw.write(line);
			bw.newLine();
			bw.flush();
		}

		// 给出反馈
		BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
				s.getOutputStream()));
		bwServer.write("文件上传成功");
		bwServer.newLine();
		bwServer.flush();

		// 释放资源
		bw.close();
		s.close();
	}
}

小结:

1、服务器端还可以用while循环来接收多个客户端的数据,但这种方式存在缺点,就是所有客户端只能上传同一类型的文件,并且所有客户端上传的数据都是保存在服务器下同一个文件中,但这种缺点可以通过多线程来克服。

2、客户端连接上服务端,两端都在等待,没有任何数据传输,因为read方法或者readLine方法是阻塞式使用shutdownInput,shutdownOutput方法能很好的解决这问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值