java中的网络编程

十六. 网络编程

  1. 网络编程三要素:IP地址、端口、协议
  • IP地址的组成:网络号段+主机号段
    A类:第一号段为网络号段+后三段的主机号段
    一个网络号:256256256 = 16777216
    B类:前二号段为网络号段+后二段的主机号段
    一个网络号:256*256 = 65536
    C类:前三号段为网络号段+后一段的主机号段
    一个网络号:256
  • IP地址的分类:
    A类 1.0.0.1—127.255.255.254 (1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址) (2)127.X.X.X是保留地址,用做循环测试用的。
    B类 128.0.0.1—191.255.255.254 172.16.0.0—172.31.255.255是私有地址。169.254.X.X是保留地址。
    C类 192.0.0.1—223.255.255.254 192.168.X.X是私有地址
    D类 224.0.0.1—239.255.255.254
    E类 240.0.0.1—247.255.255.254
  • 特殊的IP地址:
    127.0.0.1 回环地址(表示本机)
    x.x.x.255 广播地址
    x.x.x.0 网络地址
  • 协议:通信的规则
    UDP:把数据打包、数据有限制、不建立连接、速度快、不可靠
    TCP:建立连接通道、数据无限制、速度慢、可靠
  • 端口号:正在运行的程序的标识。有效端口:065535,其中01024系统使用或保留端口。
  1. InetAddress(单例设计模式成员全是静态的)的成员方法:
    * public static InetAddress getByName(String host):根据主机名或者IP地址的字符串表示得到IP地址对象
    InetAddress address = InetAddress.getByName(“192.168.12.63”);
    * 获取主机名:public String getHostName()
    String name = address.getHostName();
    * 获取IP地址:public String getHostAddress()
    String ip = address.getHostAddress();

3. UDP协议接收数据:在这里插入图片描述

	1. 创建接收端Socket对象
	2. 创建一个数据包(接收容器)
	3. 调用Socket对象的接收方法接收数据
	4. 解析数据包,并显示在控制台
	5. 释放资源
	> UDP协议发送数据:
	1. 创建发送端Socket对象
	2. 创建数据,并把数据打包
	3. 调用Socket对象的发送方法发送数据包
	4. 释放资源

DatagramSocket:此类表示用来发送和接收数据报包的套接字。具体方法查看api
DatagramPacket:此类表示数据报包。数据报包用来实现无连接包投递服务。具体方法查看api

案例:多线程实现聊天

/*聊天线程管理类:*/
public class ChatRoom {
	public static void main(String[] args) throws IOException {
		DatagramSocket dsSend = new DatagramSocket();
		DatagramSocket dsReceive = new DatagramSocket(12306);
		SendThread st = new SendThread(dsSend);
		ReceiveThread rt = new ReceiveThread(dsReceive);

		Thread t1 = new Thread(st);
		Thread t2 = new Thread(rt);

		t1.start();
		t2.start();
	}
}
/*接收数据线程类:*/
public class ReceiveThread implements Runnable {
	private DatagramSocket ds;
	public ReceiveThread(DatagramSocket ds) {
		this.ds = ds;
	}
	
	@Override
	public void run() {
		try {
			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);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
/*发送数据线程类:*/
public class SendThread implements Runnable {
	private DatagramSocket ds;
	public SendThread(DatagramSocket ds) {
		this.ds = ds;
	}

	@Override
	public void run() {
		try {
			// 封装键盘录入数据
			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.12.92"), 12345);
				DatagramPacket dp = new DatagramPacket(bys, bys.length,
						InetAddress.getByName("192.168.12.255"), 12306);

				// 发送数据
				ds.send(dp);
			}
			// 释放资源
			ds.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

4. TCP协议发送数据:

在这里插入图片描述
1. 创建发送端的Socket对象:这一步如果成功,就说明连接已经建立成功了。
2. 获取输出流,写数据
3. 释放资源
连接被拒绝。TCP协议一定要先开服务器端。java.net.ConnectException: Connection refused: connect
> TCP协议接收数据:
1. 创建接收端的Socket对象
2. 监听客户端连接。返回一个对应的Socket对象
3. 获取输入流,读取数据显示在控制台
4. 释放资源

案例:客户端、服务端一读一写

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

		// 获取输出流
		OutputStream os = s.getOutputStream();
		os.write("今天天气很好,适合睡觉".getBytes());

		// 获取输入流
		InputStream is = s.getInputStream();
		byte[] bys = new byte[1024];
		int len = is.read(bys);// 阻塞
		String client = new String(bys, 0, len);
		System.out.println("client:" + client);

		// 释放资源
		s.close();
	}
}
public class ServerDemo {
	public static void main(String[] args) throws IOException {
		// 创建服务器Socket对象
		ServerSocket ss = new ServerSocket(9999);

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

		// 获取输入流
		InputStream is = s.getInputStream();
		byte[] bys = new byte[1024];
		int len = is.read(bys); // 阻塞
		String server = new String(bys, 0, len);
		System.out.println("server:" + server);

		// 获取输出流
		OutputStream os = s.getOutputStream();
		os.write("数据已经收到".getBytes());

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

禁用此套接字的输出流:public void shutdownOutput()
案例2:客户端输出文本文件,服务器写入文本文件

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

		// 封装文本文件
		BufferedReader br = new BufferedReader(new FileReader(
				"InetAddressDemo.java"));
		// 封装通道内流
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				s.getOutputStream()));

		String line = null;
		while ((line = br.readLine()) != null) { // 阻塞
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		//自定义一个结束标记
		//bw.write("over");
		//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();
	}
}	
public class UploadServer {
	public static void main(String[] args) throws IOException {
		// 创建服务器端的Socket对象
		ServerSocket ss = new ServerSocket(11111);

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

		// 封装通道内的流
		BufferedReader br = new BufferedReader(new InputStreamReader(
				s.getInputStream()));
		// 封装文本文件
		BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));

		String line = null;
		while ((line = br.readLine()) != null) { // 阻塞
		// if("over".equals(line)){
		// break;
		// }
			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();
	}
}

案例三:多线程实现多个客户端上传文件

/*线程类:*/
public class UserThread implements Runnable {
	private Socket s;

	public UserThread(Socket s) {
		this.s = s;
	}

	@Override
	public void run() {
		try {
			// 封装通道内的流
			BufferedReader br = new BufferedReader(new InputStreamReader(
					s.getInputStream()));
			// 封装文本文件
			// BufferedWriter bw = new BufferedWriter(new
			// FileWriter("Copy.java"));

			// 为了防止名称冲突
			String newName = System.currentTimeMillis() + ".java";
			BufferedWriter bw = new BufferedWriter(new FileWriter(newName));

			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();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

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

		while (true) {
			Socket s = ss.accept();
			new Thread(new UserThread(s)).start();
		}
	}
}
/*客户端类:*/
public class UploadClient {
	public static void main(String[] args) throws IOException {
		// 创建客户端Socket对象
		Socket s = new Socket("192.168.12.92", 11111);

		// 封装文本文件
		// BufferedReader br = new BufferedReader(new FileReader(
		// "InetAddressDemo.java"));
		BufferedReader br = new BufferedReader(new FileReader(
				"ReceiveDemo.java"));
		// 封装通道内流
		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();
	}
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值