十六、网络编程

1.计算机网络

1.1概述

什么是网络:由(计算机)和线(网线)构造的网状结构
什么是计算机网络:不同区域的计算机,通过线路连接能够实现数据传递资源共享的方式
什么是网络编程:实现数据传递与资源共享的具体技术

1.2网络模型

概述:在实现通讯过程中软硬件结合的操作

十六、网络编程

1.3网络编程三要素

十六、网络编程

IP地址
计算机的唯一标识
有两种IP地址表示:
IPV4:分4个段,每个段最高为255;例如:192.168.1.6
IPV6:分8个段,每个段最高位FFFF;(十六进制)

IPV4分类:
A类:从1开始~126段
B类:127开始~191段
C类:192开始~223段(10个以内)
D类:224开始~239段

回环地址:127.0.0.1,代表本机测试地址


Port:
通讯软件的唯一识别:(0~65535)
0~1024: 系统已经分配或保留的端口,一般不去使用
1024以后可以使用
避开一些常用端口:例如3306,8080,1521等

协议:
TCP,UDP协议
TCP:面向连接的协议,安全但效率低--例如:打电话
UDP:无连接的协议,不安全但效率高--例如:发短信

2.网络编程

2.1INetAddress类

INetAddress类: 代表IP地址对象
可以调用相关方法得到IP地址

public class Test1 {
	public static void main(String[] args) throws UnknownHostException {
		//通过ip或主机名或域名得到ip对象
		InetAddress net1 = InetAddress.getByName("192.168.1.8");
		System.out.println(net1);
		
		//一个域名可能绑定多台服务器(多个IP)
		InetAddress[] nets = InetAddress.getAllByName("www.baidu.com");
		System.out.println(Arrays.toString(nets));
		
		InetAddress net2 = InetAddress.getLocalHost();
		System.out.println(net2);  //获取本机IP
		
	}
}

2.2TCP-客户端发数据到服务器

TCP编程:也叫做Socket编程,基于tcp协议字节流的传输协议
通讯模型: 客户端-服务器模型
服务器:
1.实例化服务器Socket对象,指定自身端口
2.监听客户端的连接,如果有客户端连接了,那么创建一个socket与客户端通讯

客户端:
1.实例化socket对象,传入服务器的ip和端口

谁先启动?  服务器先启动,有监听阻塞方法

//案例:服务器与客户端建立TCP连接后,进行通讯;
//客户端给服务器发数据,服务器也可以给客户端发数据

public class Server {
	public static void main(String[] args) throws IOException {
		//实例化服务器socket,指定自身端口
		ServerSocket serverSocket = new ServerSocket(9527);
		//调用accept监听客户端连接,如果有客户端连接了,则创建了socket对象与客户端通讯
		Socket socket = serverSocket.accept();  //阻塞方法
		System.out.println("有一个客户端连上来了");
		
		//接收数据--读
		InputStream is = socket.getInputStream();
		byte[] b = new byte[1024];
		int len = is.read(b);
		System.out.println(new String(b, 0,len));
		
		
		//服务器发送数据--写
		OutputStream os = socket.getOutputStream();
		os.write("服务器回应给客户端的数据".getBytes());
	
		IOUtils.closeAll(is,os,socket,serverSocket);
	}
}


-----Client-------
public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket = new Socket("127.0.0.1", 9527);
		
		//通过字节流发数据--写
		OutputStream os = socket.getOutputStream();
		os.write("客户端发送的数据..".getBytes());
		
		//客户端的接收--读
		InputStream is = socket.getInputStream();
		byte[] b = new byte[1024];
		int len = is.read(b);
		System.out.println(new String(b, 0,len));
		
		//统一资源关闭: 先关小的,再关大的
		IOUtils.closeAll(os,is,socket);
	}
}

十六、网络编程

十六、网络编程2.3客户端上传图片到服务器

//案例:使用tcp编程实现图片上传到服务器
//分析:先在客户端通过输入字节流读取图片资源,然后写到socket中
     //在服务器的socket中通过读字节流接收,然后再写到服务器本地
-------Server--------
public class Server {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(10086);
		Socket socket = ss.accept();
		
		//从socket中读取字节流
		InputStream is = socket.getInputStream();
		FileOutputStream fos = new FileOutputStream("d:\\a.jpg");
		byte[] b = new byte[1024];
		int len;
		while((len=is.read(b))!=-1) {
			fos.write(b, 0, len);
		}
		System.out.println("服务器接收成功~!");
		IOUtils.closeAll(fos,is,socket,ss);
	}
}


-------Client--------
public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket = new Socket("127.0.0.1", 10086);
		
		//客户端从图片中读取资源
		FileInputStream fis = new FileInputStream("b.jpg");
		byte[] b = new byte[1024];
		int len;
		OutputStream os = socket.getOutputStream();
		while((len=fis.read(b))!=-1) {
			os.write(b, 0, len);
		}
		System.out.println("上传到服务器~~");
		IOUtils.closeAll(os,fis,socket);
		
	}
}

2.4多个客户端发数据给服务器

//案例:多个客户端与服务器聊天
//服务器:
//1.来一个客户端,那么产生一个socket与客户端通讯---多线程
//2.从socket总接收文本内容,通过字符缓冲流封装

//客户端:
//1.循环从客户端录入数据

------服务器------
public class Server {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(10010);
		//死循环实时监听客户端连接
		while(true) {
			Socket socket = ss.accept();
			System.out.println("有一个客户端进行了连接...");
			new ServerThread(socket).start();//在开辟的路径中,执行socket操作
		}
	}
}


------服务器线程------
public class ServerThread extends Thread {
	private Socket socket;
	
	public ServerThread(Socket socket) {
		this.socket = socket;
	}
	
	@Override
	public void run() {
		InputStream is = null;
		BufferedReader br = null;
		try {
			is = socket.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			while(true) {
				String msg = br.readLine();
				System.out.println(msg);
				
				if(msg.equals("886")) {
					break;
				}
			}
		} catch (IOException e) {
			System.out.println("有异常中断。。。");
		}finally {
			System.out.println("有一个客户端退出了连接");
			IOUtils.closeAll(is,br,socket);
		}
		
	}
}


------客户端------
public class Clent {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket = new Socket("127.0.0.1", 10010);
		
		System.out.println("请从客户端进行录入:");
		OutputStream os = socket.getOutputStream();  //字符缓冲流包装
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		//从键盘录入
		Scanner sc = new Scanner(System.in);
	
			while(true) {
				String msg = sc.next();
				bw.write(msg);
				bw.newLine();  //换行
				bw.flush();    //刷新
				
				if(msg.equals("886")) {  //约定
					break;
				}
			}
			IOUtils.closeAll(os,bw,socket);
	}
}

十六、网络编程

3.网络编程案例

3.1注册功能

//案例:注册功能
//分析:
//1.客户端与服务器建立连接
//2.客户端准备好注册数据,拼成一个字符串;例如:{id:"1001",name:"zs",age:30}
//3.发送注册数据,服务器接收数据
//4.服务器拆分数据,取出id对应的value作为key,接收的注册信息作为value
//5.判断key在配置文件中是否存在,如果存在,则返回"已存在"
//6.不存在,把这些数据存到配置文件,并返回“注册成功”
-----服务器------
public class Server {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(9527);
		Socket socket = ss.accept();
		InputStream is = socket.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg = br.readLine(); //{id:1001,name:zs,age:30}
		String strId = msg.split(",")[0];  //{id:1001
		String id = strId.split(":")[1];   //1001
		
		//通过Properties集合去加载配置文件
		Properties p = new Properties();
		p.load(new FileInputStream("user.properties"));
		
		OutputStream os = socket.getOutputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		if(p.containsKey(id)) {
			bw.write("已存在");
			
		}else {
			Tool.saveProperties(id,msg);  //将数据存储到配置文件
			bw.write("注册成功");
		}
		bw.newLine();
		bw.flush();
		
		IOUtils.closeAll(bw,os,br,is,socket);
		
	}
}


-----客户端------
public class Client {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1",9527);
		OutputStream os = socket.getOutputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		
		String json = getData(); //{id:1001,name:zs,age:30}
		//发数据
		bw.write(json);
		bw.newLine();
		bw.flush();
		
		InputStream is = socket.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg = br.readLine();
		System.out.println("服务器响应:"+msg);
		
		IOUtils.closeAll(is,br,os,bw,socket);
	}

	private static String getData() {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入ID:");
		String id = sc.next();
		System.out.println("请输入用户名:");
		String name = sc.next();
		System.out.println("请输入年龄:");
		int age = sc.nextInt();
		return "{id:"+id+",name:"+name+",age:"+age+"}";
	}
}

----user.properties在src目录下建一个----

----工具类----
public class Tool {
	public static void saveProperties(String id, String msg) throws FileNotFoundException, IOException {
		Properties properties = new Properties();
		properties.put(id, msg);
		properties.store(new FileOutputStream("user.properties"), "");
	}
}

----------CloseAll------
public class CloseAll {
	public static void closeAll(Closeable... closeable) throws IOException {
		if(closeable!=null) {
			for (Closeable c: closeable) {
				c.close();
			}
		}
	}
}

3.2登录功能

/**
 * 1. 用户登录:
	客户端:
	输入ID,name;并拼接成字符串,例如“{id:1001,name:zs}”
	将该字符串传到服务器;
	服务器:
	在服务器中根据拆分的id值去匹配配置文件user.properties中是否存在key为1001的值
	如果有则取出value,拆分出name的值;和传过来的json数据里面的id和name比较
	匹配成功则返回“登录成功”到客户端;如果不匹配,则返回“登录失败”到客户端  
 *  */
-----------Client---------------
public class Client {

	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket = new Socket("127.0.0.1",9090);
		OutputStream os = socket.getOutputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		
		String json = getData();  //{id:1001,name:zs,age:30}
		
		//发数据
		bw.write(json);
		bw.newLine();
		bw.flush();
		
		InputStream is = socket.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg = br.readLine();
		System.out.println("服务器响应:"+msg);
		OutputStream osa=socket.getOutputStream();
		BufferedWriter bwa = new BufferedWriter(new OutputStreamWriter(osa));
		
		System.out.println("=====登录界面======");
		//登录
	
		
		String jsons = getlogin();
			
		//发登录的数据给服务器
		bwa.write(jsons);
		bwa.newLine();
		bwa.flush();
		
		
		System.out.println(br.readLine());
		
		CloseAll.closeAll(is,br,bw,os,osa,bwa,socket);
	}
	private static String getlogin() {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入用户名(ID):");
		String id = scanner.next();
		System.out.println("请输入姓名(name):");
		String name = scanner.next();
		return "id:"+id+",name:"+name+"";
	}
	private static String getData() {
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入ID:");
		String id=sc.next();
		System.out.println("请输入用户名:");
		String name=sc.next();
		System.out.println("请输入年龄:");
		int age=sc.nextInt();
		return "id:"+id+",name:"+name+",age:"+age;
		
	}

}

---------------Server------------------
public class Server {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(9090);
		Socket socket = ss.accept();
		
		//接受客户端的数据,并且剪切数据
		InputStream is = socket.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg = br.readLine();
		String strId = msg.split(",")[0];
		String id = msg.split(":")[1];
		
		//对文件进行加载(读取内部文件)
		Properties pro = new Properties();
		pro.load(new FileInputStream("users.properities"));
		
		OutputStream os = socket.getOutputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		if(pro.containsKey(id)) {
			System.out.println("已经存在");
		}else {
			Tools.saveProperities(msg);
			bw.write("注册成功");
		}
		bw.newLine();
		bw.flush();
		
		//接受客户端的数据,并且剪切
		InputStream isa = socket.getInputStream();
		BufferedReader bra = new BufferedReader(new InputStreamReader(isa));
		String msgs = bra.readLine();
		
		//先剪切用户名
		String strIds = msgs.split(",")[0];
		String ids = strIds.split(":")[1];
		
		//剪切密码
		String strName = msgs.split(",")[1];
		String name=strName.split(":")[1];
		
		//读取内部文件
		Properties p = new Properties();
		p.load(new FileInputStream("users.properities"));
		
		//将获取客户端的数据,对文件剪切的内容进行比对
		OutputStream osa = socket.getOutputStream();
		BufferedWriter bwa = new BufferedWriter(new OutputStreamWriter(osa));
		
		if(p.containsKey("id")&&p.containsKey("name")) {
			bw.write("登陆成功!");
		}else {
			bw.write("您输入的用户名或姓名有误!");
		}
		
		CloseAll.closeAll(bw,os,br,is,isa,bra,osa,bwa,socket);
	}

}

----------------工具类-------------------
public class Tools {
	public static void saveProperities(String msg) throws FileNotFoundException, IOException {
		Properties pro = new Properties();
		String[] str = msg.split(",");
		
		for(int i =0;i<str.length;i++) {
			String[] str1 = str[i].split(":");
			pro.put(str1[0], str1[1]);
		}
			
		pro.store(new FileOutputStream("users.properities"),"");	
	}
}

-------------------CloseAll-------------------
public class CloseAll {
	public static void closeAll(Closeable... closeable) throws IOException {
		if(closeable!=null) {
			for (Closeable c: closeable) {
				c.close();
			}
		}
	}
}

3.3聊天室程序

十六、网络编程

//案例:聊天室程序
//分析: 多人聊天---多线程
//1.通过多线程形式接收多个客户端的连接
//2.客户端要录入姓名,传入服务器接收,并存储到线程中
//(注意:客户端的发送和接收要分为两个线程,才能方便群发)
//3.服务器给客户端回应“欢迎进入聊天室”
//4.该客户端就可以实时发数据聊天了
//5.要实现服务器群发信息给客户端,需要先将所有线程对象存储
//6.退出方式,客户端退出,其他用户应该都知道

-------服务器-------
public class Server {
	public static List<ServerThread> list = new ArrayList<ServerThread>();
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(9527);
		//多线程方式监听及创建socket
		while(true) {
			Socket socket = ss.accept();
			System.out.println("有一个客户端进来了");
			ServerThread st = new ServerThread(socket);
			st.start();
			list.add(st);  //存储线程对象
		}
	}
}


------服务器线程-------
public class ServerThread extends Thread {
	private Socket socket;
	
	private BufferedReader br;
	private BufferedWriter bw;
	
	public ServerThread(Socket socket) throws IOException {
		this.socket = socket;
		br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
	}
	
	@Override
	public void run() {
	
		try {
			sendHello();  //欢迎
			
			while(true){
				String name = this.br.readLine(); //读取到数据后,发给自身
				String msg = this.getName()+"说:"+name;
				//循环遍历线程对象,除了自己,都发一份出去
				for(ServerThread st : Server.list) {
					if(st!=this) {
						st.bw.write(msg);
						st.bw.newLine();
						st.bw.flush();
					}
				}
			}
		} catch (Exception e) {
			String msg = this.getName()+"退出了聊天室";  //群发退出信息
			Server.list.remove(this);  //将当前线程对象在集合中移除
			
			for(ServerThread st : Server.list) { //移除后群发
				try {
					st.bw.write(msg);
					st.bw.newLine();
					st.bw.flush();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			
		}finally {
			IOUtils.closeAll(bw,br,socket);
		}
	}

	private void sendHello() throws IOException {
		String name = br.readLine(); //读取到数据后,发给自身
		String msg = "【温馨提示】:欢迎"+name+"进入聊天室";
		this.setName(name);  //记录客户的访问
		bw.write(msg);
		bw.newLine();
		bw.flush();
	}
}


------客户端-------
public class Client {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1",9527);
		
		//客户端读写分离
		new WriteClient(socket).start();
		
		new ReadClient(socket).start();

	}
}



-------客户端写线程-------
public class WriteClient extends Thread {
	private Socket socket;
	
	public WriteClient(Socket socket) {
		this.socket = socket;
	}
	
	@Override
	public void run() {
		OutputStream os = null;
		BufferedWriter bw = null;
		try {
			os = socket.getOutputStream();
			bw = new BufferedWriter(new OutputStreamWriter(os));
			System.out.println("请输入用户名:");
			Scanner sc = new Scanner(System.in);
			
			while(true) {
				String name = sc.next(); //第一次是输入名字,后面就是聊天内容
				bw.write(name);
				bw.newLine();
				bw.flush();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			IOUtils.closeAll(os,bw,socket);
		}
		
	}
}



-------客户端读线程--------
public class ReadClient extends Thread {
	private Socket socket;
	
	public ReadClient(Socket socket) {
		this.socket = socket;
	}
	
	@Override
	public void run() {
		InputStream is = null;
		BufferedReader br = null;
		try {
			is = socket.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			while(true) {
				String msg = br.readLine();
				System.out.println(msg);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			IOUtils.closeAll(is,br,socket);
		}
		
	}
}
上一篇:获取系统临时文件目录,生成txt文件


下一篇:2021-11-07