Java基本网络编程笔记--视频总结

一基本概念

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IP

用来标识网络中的一个通信实体的地址。
通信实体可以是 计算机,路由器等。
路由器:连接两个或多个网络的网络设备。
IPV4: 32位地址, 以点分十进制表示,192.168.0.1
IPV6:128位(16字节) 写成8个16位的无符号整数,每个整数用4个16进制位表示,数之间用(冒号:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
特殊的IP:
127.0.0.1 本机地址
192.168.0.0 – 192.16.255.255 私有地址,属于非注册地址,专门为组织机构内部使用。

/**
 * IP : 定位一个节点:计算机 路由器 通讯设备等等
 * InetAddress  : 封装计算机的ip 地址,没有端口。
 * 1.getLocalHost : 本机
 * 2.getByName : 根据域名DNS或Ip地址  ---解析--》IP
 * 
 * .两个成员方法:
 * 1.getHostAddress : 返回地址
 * 2.getHostName: 返回计算机名
 * @author admin
 *
 */
public class IPTest {
	public static void main(String[] args) throws UnknownHostException {
		//使用getLocalHost方法创建InetAddress对象  本机
		InetAddress addr = InetAddress.getLocalHost();
		System.out.println(addr.getHostAddress()); //返回: 本机地址
		System.out.println(addr.getHostName()); //返回: 本机计算机名字
		
		
		//根据域名得到InetAddress 对象
		addr = InetAddress.getByName("www.shsxt.com");
		System.out.println(addr.getHostAddress()); //返回: shsxt服务器的ip
		System.out.println(addr.getHostName()); //输出: www.shxst.com
		
		//根据Ip得到InetAddress 对象
		addr = InetAddress.getByName("123.56.138.176");
		System.out.println(addr.getHostAddress()); //返回shsxt的ip : 123.56.138.176
		System.out.println(addr.getHostName()); //输出ip 而不是域名。如果这个ip 地址不存在或者DNS服务器不允许进行IP地址和域名的映射
		 //getHostName放法直接返会这个Ip地址。
	}
	
}

端口

IP用来表示一台计算机。
端口表示是一个16位的二进制整数,2个字节,对应十进制的0—65535
端口是虚拟的概念。用来区分软件的
通过端口,可以在一个主机上运行多个网络应用程序。
公认端口 0–1023
注册端口 1024 --49151
动态/私有端口 49152 – 65535

查看所有端口: netstat -ano
查看指定端口: netstat -ano | findstr “808”
查看指定进程: tasklist | findstr “808”
查看具体程序:使用任务管理器查看PID

/**
 * 端口
 * 1.区分软件
 * 2.2个字节 0 --65535 UDP TCP协议不一样
 * 3.同一个协议端口不能冲突
 * 4.定义端口越大越好
 * @author admin
 *1.构造器
 *new InetSocketAddress(地址|域名|, 端口);
 *2.方法
 *getAddress() : 地址
 *getPort()  : 端口
 *InetSocketAddress
 */
public class PortTest {
	
	public static void main(String[] args) {
		//包含端口
		InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
		InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",9000);
		
		System.out.println(socketAddress.getHostName());
		System.out.println(socketAddress.getAddress());
		
		System.out.println(socketAddress2.getAddress());
		System.out.println(socketAddress2.getPort());
		
	}
}

URL :统一资源定位器

在这里插入图片描述

/**
 * URL : 统一资源定位器 互联网三大基石之一(html http) 区分资源
 * 组成部分
 * 1.协议
 * 2.域名 、计算机
 * 3.端口 :默认80
 * 4.资源文件名
 * @author admin
 *
 */
public class URLTest01 {
	
	public static void main(String[] args) throws MalformedURLException {
		URL url = new URL("http://www.baidu.com:80/index.html?uname=shsxt&age=18#a");
		//获取四个值
		System.out.println("协议: " + url.getProtocol());
		System.out.println("域名IP: " + url.getHost());
		System.out.println("端口: " + url.getPort());
		System.out.println("请求资源1: " + url.getFile());
		System.out.println("请求资源2: " + url.getPath());
		
		//参数
		System.out.println("参数:" + url.getQuery());
		//锚点
		System.out.println("锚点:" + url.getRef());
	}
	
}

简单网络爬虫

public class SpiderTest{
	public static void main(String[] args){
		//获取URL
		URL  url = new URL("http://www.jd.com");
		//下载资源
		InputStream is = url.openStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
		String str = null;
		while(null != (str=br.readline())){
			System.out.println(str);
		}
		br.close();
		//分析
		//处理
	}
}

UDP编程

DataGramSocket : 用于发送或接收数据包的套接字
DatagramPacket : 数据包

/**
  *发送端
 *1.使用 DatagramSocket   指定端口 创建发送端
 *2.准备数据  一定要转成字节数组
 *3.封装成DatagramPacket 包裹,需要指定目的地
 *4.发送包裹 send(DatagramPacket p)
 * 5.释放资源
 
 * @author admin
 *
 */
public class UdpClient {
	public static void main(String[] args) throws IOException {
		System.out.println("发送端启动中。。。。");
		//1.使用 DatagramSocket   指定端口 创建发送端
		DatagramSocket client = new DatagramSocket(6666);
		//2.准备数据  一定要转成字节数组
		String str = "我爱你";
		byte[] datas = str.getBytes();
		 //3.封装成DatagramPacket 包裹,需要指定目的地
		DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",8888));
		
		//4.发送包裹 send(DatagramPacket p)
		client.send(packet);
		 // 5.释放资源
		client.close();	  
	}
}
/**
 *接收端
 *1.使用 DatagramSocket   指定端口 创建接收端
 *2.准备容器  封装成DataGramPacket 包裹
 *3.阻塞式接收包裹 receive (DatagramPacket p)
 *4.分析数据
 *  byte[] getData()
 *         getLength()
 * 5.释放资源
 * 
 * @author admin
 *
 */
public class UdpServer {
	public static void main(String[] args) throws IOException {
		System.out.println("接收端启动中。。。。");
		 //1.使用 DatagramSocket   指定端口 创建接收端
		DatagramSocket server = new DatagramSocket(8888);
		 //2.准备容器  封装成DataGramPacket 包裹
		byte[] container = new byte[1024*60];
		DatagramPacket packet = new DatagramPacket(container,0,container.length);
		 //3.阻塞式接收包裹 receive (DatagramPacket p)
		server.receive(packet);//阻塞式
		 //4.分析数据
		  byte[]  msg = packet.getData();
		  int len = packet.getLength();
		  System.out.println(new String(msg,0,len));
		//5.释放资源
		  server.close();
	}
}

UDP–操作基本对象

//发送端
public class UdpTypeClient{
	public static void main(String[] args){
		//1.利用DatagramSocket 创建发送端 指定端口
		DatagramSocket client = new DatagramSocket(8888);
		//2.准备数据  一定转化为字节数组
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
		//写出
		dos.writeUTF("爱你");
		dos.writeInt(3);
		dos.writeBoolean(false);
		dos.flush();
		byte[] datas = baos.toByteArray();
		//3.封装为DatagramPacket() 指定发送位置
		DatagramPacket packet = new DatagramPacket(datas,0, datas.length, new InetSocketAddress("localhost",9999));
		//4.发送
		client.send(packet);
		//5.关闭资源
		client.close();		
	}
}
接收端
public class UdpTypeServer{
	public static void main(String[] args){
		//1.利用DatagramSocket 指定端口 创建接收端
		DatagramSocket server = new DatagramSocket(9999);
		//2.准备容器  并封装为DatagramPacket()
		byte[] container = new byte[1024*64];
		DatagramPacket packet = new DatagramPacket(container,0,container.length);
		//3.阻塞式接收
		server.receive(packet);
		//4.数据处理 并转回到原来的类型
		byty[] datas = packet.getByte();
		int len = packet.getLength();
		DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
		//读出,与写出顺序一致
		String msg = dis.readUTF();
		int age = dis.readInt();
		boolean flag = dis.readBoolean();
		System.out.println(flag):
		//5.释放资源
		server.close();
	}
}

UDP传文件

/**
 * 文件发送: 发送端
 * @author admin
 *
 */
public class UdpFileClient {
	public static void main(String[] args) throws IOException {
		System.out.println("启动子。。。");
		//1.利用DatagramSocket 指定端口 创建发送端
		DatagramSocket client = new DatagramSocket(8888);
		//2.准备数据  一定转化为字节数组
		byte[] datas = UtileFile.fileToByteArray("C:\\Users\\admin\\Desktop\\D\\eclipse-workspace\\Net_study02\\src\\com\\sxt\\udp\\111.jpg");
		//3.封装为 DatagramPacket
		DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",5789));
		//4.发送
		client.send(packet);
		//5.释放资源
		client.close();
	}
}

/**
 * 文件存储 :接收端
 * @author admin
 *
 */
public class UdpFileServer {
	public static void main(String[] args) throws IOException {
		System.out.println("启动子。。。");
		//1.
		DatagramSocket server = new DatagramSocket(5789);
		//2.
		byte[] container = new byte[1024*60];
		DatagramPacket packet = new DatagramPacket(container,0,container.length);
		//3.
		server.receive(packet);
		//4.数据处理
		byte[] datas = packet.getData();
		int len = packet.getLength();
		UtileFile.ByteArrayToFile(datas, "src/copy.jpg");
		//5.释放资源
		server.close();
	}
}

//图片 – 》 文件
//1.图片–程序—字节数组
//2.字节数组 – 程序 – 文件

public class UtileFile {
		
	//1. 图片 -- 》字节数组
	public static byte[] fileToByteArray(String path) throws IOException {
		//1.图片 --- 》 程序  FileInputStream
		//2.程序------》字节数组  ByteArrayOutputstream
		
		//1.创建源
		File f = new File(path);
		byte[] dest = null;
		//2.选择流
		InputStream is = null;
		ByteArrayOutputStream baos = null;
		
		try {
			//3.操作
			is = new FileInputStream(f);
			baos = new ByteArrayOutputStream();
			byte[] flush = new byte[1024*10];
			int len = -1;
			while((len = is.read(flush)) != -1) {
				baos.write(flush,0,len); //写出到字节数组中
			}
			baos.flush();
			return baos.toByteArray();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//4.释放资源
			if(null != is) {
				is.close();
			}
		}
		
		return null;
	}
	
	//2.字节数组 ---- 》文件
	public static void ByteArrayToFile(byte[] bt, String path) throws IOException {
		//1.字节数组 ---- 》 程序 ByteArrayInputStream
		//2.程序 --- 》 文件        FileOutputStream
		//1.创建源
		//byte[] src =bt;
		File f = new File(path);
		//2.选择流
		InputStream baos = null;
		OutputStream os = null;
		
		
		try {
			//3.操作
			baos = new ByteArrayInputStream(bt);
			os = new FileOutputStream(f);
			byte[] flush  = new byte[5];
			int len = -1;
			while((len = baos.read(flush)) != -1){
				os.write(flush,0,len); //写出到文件
			}
			os.flush();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(null != os) {
				os.close();
				
			}
		}	
	}
}

UDP实例 – 在线咨询

多线程 实现 双方交互

//发送类
public class TalkSend implements Runnable{
	private DatagramSocket client ;
	private String toIp;
	private int toPort;
	BufferedReader  reader;
	public TalkSend(int port, String toIp, int toPort){
		this.toIp = toIp;
		this.toPort = toPort;
		client = new DatagramSocket(port);
		  reader = new BufferedReader(new InputStreamReader(System.in));
	}
//重写
	public void run(){
		while(true){
			//2.数据  封装
			String data;
			data  = reader.readLine();
			byte[] datas = data.getBytes();
			//3.封装
			DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
			//4.发送
			client.send(packet);
			if(datas.equals("bye")){
				break;
			}
		}
		//5.释放资源
		client.close();
	}
}
//接收类
public class TalkReceive implements Runnable{
	DatagramSocket server;
	private String from;
	public TalkReceive(int port, String from){
		this.from = from;
		server = new DatagramSocket(port);
	}
	public void run(){
			while(true) {
			byte[] container = new byte[1024*60];
			DatagramPacket packet = new DatagramPacket(container,0,container.length);
			//3.
			try {
				server.receive(packet);
				//4.数据处理分析
				byte[] datas = packet.getData();
				int len = packet.getLength();
				String data = new String(datas,0,len);
				System.out.println(from+":"+data);
				if(datas.equals("bye")) {
					break;
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
		//5.释放资源
		server.close();		
	}
}

TCP编程

在这里插入图片描述
简单测试

//服务端: 流程
1. 指定端口, 使用ServerSocket 创建服务端
2. 阻塞式等待连接accept
3. 操作:输入输出操作
4. 释放资源
 public class Server {
 	public static void main(String[] args){
 		//1.指定端口  使用ServerSocket 创建服务端
 		ServerSocket server = new ServerSocket(8888);
 		//2.阻塞式等待连接 accept
 		Socket client = server.accept();
 		System.out.println("一个客户端建立连接");
 		//3.输出输入操作
 		DataInputStream dis = new DataInputStream(client.getInputStream());
 		String str = dis.readUTF();
 		System.out.println(str);
 		//4.释放资源
 		dis.close();
 		client.close();
 		server.close();
 	}
 }
//客户端 : 流程
1.建立连接 : 使用Socket创建客户端 + 服务器地址和端口
2. 操作:输入输出
3. 释放资源

public class client{
	public static void main(String[] args){
		System.out.println("------------Client----------");
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2. 操作
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		String str = "Helloc";
		dos.writeUTF(str);
		dos.flush();
		//3.释放资源
		dos.close();
		client.close();
	}
}

网络登录功能分解
1.单向:客户端向服务器发送字符串,服务器获取字符串并输出
2.双向:服务器给客户端反馈,客户端得到反馈并输出。
3.文件:客户端向服务器端上传文件,服务器端获取文件并反馈结果
4.多线程:服务器端接收多个客户端的请求,并给出反馈 每个客户请求开启一个线程。

1.单向

/**
 * 单向 : 服务端
 * @author admin
 *
 */
public class LoginServer {
	public static void main(String[] args) throws IOException {
		System.out.println("---------Server---------");
		
		//1.创建
		ServerSocket server = new ServerSocket(8888);
		//2.阻塞式等待连接
		Socket client = server.accept();
		System.out.println("一个客户端建立连接");
		//3.操作
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String datas = dis.readUTF();
		//分析
		String[] dataArray = datas.split("&");
		for(String info: dataArray) {
			String[] userInfo = info.split("=");
			if(userInfo[0].equals("uname")) {
				System.out.println("你的用户名为:"+ userInfo[1]);
			}else if(userInfo[0].equals("upwd")) {
				System.out.println("你的密码为:"+ userInfo[1]);
			}
		}
		//4.释放资源
		dis.close();
		client.close();
		server.close();
	}	
}
/**
 * 单向: 客户端
 * @author admin
 *
 */
public class LoginClient {
	public static void main(String[] args) throws IOException {
		
		System.out.println("--------Client--------");
		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入用户名:");
		String uname = console.readLine();
		System.out.println("请输入密码:");
		String upwd = console.readLine();
		
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2.操作
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
		dos.flush();
		//3.释放资源
		dos.close();
		client.close();
	}
}

双向

/**
 * 双向模拟登录 -----客户端
 * @author admin
 *
 */
public class LoginTwoWayClient {
	public static void main(String[] args) throws IOException {
		
		System.out.println("-----Client-------");
		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入你的用户名:");
		String uname = console.readLine();
		System.out.println("请输入你的密码:");
		String upwd = console.readLine();
		
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2.操作
		//写出
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF("uname="+uname+"&"+"upwd=" + upwd);
		dos.flush();
		
		//接收
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String result = dis.readUTF();
		System.out.println(result);
		
		//3.释放资源
		dos.close();
		dis.close();
		client.close();
		
	}
}
//双向模拟登录-----------服务端
public class LoginTwoWayServer {
	public static void main(String[] args) throws IOException {
		System.out.println("-------Server--------");
		//1.创建
		ServerSocket server = new ServerSocket(8888);
		//2.阻塞式等待
		Socket client = server.accept();
		System.out.println("一个客户端建立连接");
		//3.操作
		//接收数据
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String datas = dis.readUTF();
		//
		String uname = "";
		String upwd = "";
		String[] userArray = datas.split("&");
		for(String info : userArray) {
			String[] userInfo = info.split("=");
			if(userInfo[0].equals("uname")){
				System.out.println("你的用户名为:"+ userInfo[1]);
				uname = userInfo[1];
			}else if(userInfo[0].equals("upwd")) {
				System.out.println("你的密码为:"+ userInfo[1]);
				upwd = userInfo[1];
			}
		}
		
		//发送
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		
		if(uname.equals("sxt") && upwd.equals("123")) {//成功
			dos.writeUTF("登录成功");
		}else {//失败
			dos.writeUTF("登录失败");
		}
		dos.flush();
		//4.释放资源
		dis.close();
		dos.close();
		client.close();
		server.close();
		
	}
}

上传文件-----客户端

/**
 * 上传文件
 * @author admin
 *
 */
public class FileClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("---------Client--------");
		
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2.操作
		InputStream is = new BufferedInputStream(new FileInputStream("src/copy.jpg"));
		OutputStream os = new BufferedOutputStream(client.getOutputStream());
		byte[] flush = new byte[1024];
		int len = -1;
		 while((len = is.read(flush)) != -1) {
			 os.write(flush,0,len);
		 }
		 os.flush();
		 
		 //4.释放资源
		 os.close();
		 is.close();
		 client.close();
	}
}

存储文件------服务端

/**
 * 存储文件
 * @author admin
 *
 */
public class FileServer {
	public static void main(String[] args) throws IOException {
		
		System.out.println("-------Server-------");
		//1.建立
		ServerSocket server = new ServerSocket(8888);
		//2。阻塞式等待接收连接
		Socket client = server.accept();
		System.out.println("一个客户端建立了连接");
		//3.操作:文件拷贝
		InputStream is = new BufferedInputStream(client.getInputStream());
		OutputStream os = new BufferedOutputStream(new FileOutputStream("src/tcp.jpg"));
		
		byte[] flush = new byte[1024];
		int len = -1;
		while((len = is.read(flush)) != -1) {
			os.write(flush,0,len);
		}
		os.flush();
		//4.释放资源
		os.close();
		is.close();
		client.close();
		server.close();	
	}
}

多用户模拟登录
客户端

public class LoginMutilClient {
	public static void main(String[] args) throws IOException {
		
		System.out.println("------Client----------");	
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2.操作		
		new Send(client).send();		
		new Receive(client).receive();	
		//释放资源
		client.close();		
	}
		
	//发送
	static class Send{
		private DataOutputStream dos ;
		private Socket client;
		private BufferedReader console ;
		private String msg ;
		
		public Send(Socket client) throws IOException {
			console = new BufferedReader(new InputStreamReader(System.in));
			this.client = client;	
			this.msg = init();
			dos = new DataOutputStream(client.getOutputStream());			
		}
		
		//初始化
		private String init() throws IOException {
			System.out.println("请输入你的用户名:");
			String uname = console.readLine();
			System.out.println("请输入你的用户名:");
			String upwd = console.readLine();
			return "uname="+uname+"&"+"upwd=" + upwd;
		}
				
		public void send() throws IOException {
			dos.writeUTF(msg);
			dos.flush();
		}		
	}
	//接收
	static class Receive{
		private DataInputStream dis ;
		private Socket client;
		public Receive(Socket client) throws IOException{
			this.client = client;
			dis = new DataInputStream(client.getInputStream());	
		}
		
		public void receive() throws IOException {
			String result = dis.readUTF();
			System.out.println(result);
		}
	}	
}

服务端

/**
 * 多个客户端请求
 * @author admin
 *
 */
public class LoginMutilServer {
	public static void main(String[] args) throws IOException {
		System.out.println("---------Server----------");
		//1.创建
		ServerSocket server = new ServerSocket(8888);
		boolean isRunning = true;
		//2.等待连接
		while(isRunning) {
			Socket client = server.accept();
			System.out.println("一个客户端建立连接");	
			new Thread(new Channel(client)).start();
		}		
		server.close();		
	}
	
	static class Channel implements Runnable{
		
		private Socket client;
		//输入流
		private DataInputStream dis;
		//输出流
		private DataOutputStream dos;
		public Channel(Socket client) throws IOException  {
			this.client = client;
			//输入
			try {
				dis = new DataInputStream(client.getInputStream());
				//输出
				dos = new DataOutputStream(client.getOutputStream());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				//释放
				release();
			}		
		}	
		//接收数据
		private String receive() throws IOException{
			String datas = "";
			datas = dis.readUTF();
			return datas;											
		}
		//释放资源
		private void release() throws IOException {
			if(null != dos) {
				dos.close();
			}
			if(null != dis) {
				dis.close();			
						}
			if(null != client) {
				client.close();
			}			
		}
		//发送数据
		private void send(String msg) throws IOException {
			dos.writeUTF(msg);
			dos.flush();
		}
		
		@Override
		public void run() {
			
			String uname = "";
			String upwd = "";
			//分析
			try {
				String[] dataArray = receive().split("&");
				for(String info : dataArray) {
					String[] useInfo = info.split("=");
					if(useInfo[0].equals("uname")) {
						System.out.println("你的用户名为:" + useInfo[1]);
						uname = useInfo[1];
					}else if(useInfo[0].equals("upwd")) {
						System.out.println("你的密码为:" + useInfo[1]);
						upwd = useInfo[1];
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//发送
			if(uname.equals("sxt") && upwd.equals("123")) {
				try {
					send("登录成功");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else {
				try {
					send("登录失败");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}						
		}	
	}	
}

聊天室

服务端:一个线程专门发消息 一个线程专门收消息
客户端: 一个线程专门发消息 一个线程专门收消息

一:目标 : 实现一个用户正常收发消息

/**
 * 在线聊天室 : 客户端
 * 目标: 实现一个客户端可以正常收发消息
 * @author admin
 *
 */
public class Client {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("---------Server---------");
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入信息:");
		String msg = reader.readLine();
		
		//1.建立连接 利用Socket + 服务的IP 和 端口
		Socket client = new Socket("localhost",8888);
		//2.操作
		//发
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF(msg);
		dos.flush();
		//获取消息
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String result = dis.readUTF();
		System.out.println(result);
		//3.释放资源
		dos.close();
		client.close();
		
	}
}
/**
 * 在线聊天室: 服务端
 * 目标: 实现一个客户正常收发消息
 * @author admin
 *
 */
public class Chat {
	public static void main(String[] args) throws IOException {
		
		System.out.println("----------Server---------");
		
		//1.创建利用ServerSocket  指定端口
		ServerSocket server = new ServerSocket(8888);
		//2.阻塞式等待连接accept()
		Socket client = server.accept();
		System.out.println("一个客户端 建立连接");
		//3.操作
		//接收消息
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String msg = dis.readUTF();
		//返回消息
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF(msg);
		dos.flush();
		//4.释放资源
		dis.close();
		client.close();
		server.close();
	}
}

二:收发多条消息
在收发消息处加个循环就好 另外注意客户端读取键盘输入 加到 循环里
还有 循环条件最好整个变量 , 不然会报错—“unreachable code”

/**
 * 在线聊天室: 服务端
 * 目标: 实现一个客户多次正常收发消息
 * @author admin
 *
 */
public class MutilTalkChat {
	public static void main(String[] args) throws IOException {
		
		System.out.println("----------Server---------");
		
		//1.创建
		ServerSocket server = new ServerSocket(8888);
		//2.阻塞式等待连接
		Socket client = server.accept();
		System.out.println("一个客户端 建立连接");
		//3.操作
		//接收消息
		boolean isRunning = true;
		DataInputStream dis = new DataInputStream(client.getInputStream());;
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		while(isRunning) {			
			String msg = dis.readUTF();		
			
			//发消息
			dos.writeUTF(msg);
			dos.flush();
		
		}
		//4.释放资源
		dis.close();
		client.close();
		server.close();
	}
}
/**
 * 在线聊天室 : 客户端
 * 目标: 实现一个客户端可以多次正常收发消息
 * @author admin
 *
 */
public class MutilTalkClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		
		
		System.out.println("---------Server---------");
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入信息:");
		
		//1.建立连接
		Socket client = new Socket("localhost",8888);
		//2.操作
		boolean isRunning = true;
		DataOutputStream dos =  new DataOutputStream(client.getOutputStream());
		DataInputStream dis =  new DataInputStream(client.getInputStream());
		
		while(isRunning) {
			//发消息			
			 String msg = reader.readLine();
			dos.writeUTF(msg);
			dos.flush();
			//获取消息
			String result = dis.readUTF();
			System.out.println(result);
		}

		//释放资源
		dos.close();
		dis.close();
		client.close();
		
	}
}

三:多个客户 同时 收发多条消息
1.首先对服务端 使用多线程并进行封装

/**
 * 服务端
 * 使用多线程 封装 : 实现多个用户发送多条消息
 * @author admin
 *
 */
public class MultiChat {
	
	public static void main(String[] args) throws IOException {
		
		System.out.println("----------Server---------");
		
		//1.创建
		ServerSocket server = new ServerSocket(9999);
		//2.阻塞式等待连接
		while(true){
			Socket client = server.accept();
			System.out.println("一个客户端 建立连接");
			//3.操作		
			new Thread(new Channel(client)).start();
		}		
	}	
}

//一个客户 一个channel
class Channel implements Runnable{
	DataInputStream dis = null;
	DataOutputStream dos =null;
	private Socket client;
	private boolean isRunning ;
	
	public Channel(Socket client) throws IOException {
		this.client = client;
		dis = new DataInputStream(client.getInputStream());
		dos = new DataOutputStream(client.getOutputStream());
		isRunning = true;
	}
	
	//发消息
	private void send(String msg) {
		try {
			dos.writeUTF(msg);
			dos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("------发——————--");
			release();
		}
		
	}
	//收消息
	private String receive() {
		String msg1 = "";
		try {
			msg1 = dis.readUTF();
		} catch (IOException e) {
			System.out.println("------收——————--");
			release();
		}		
		return msg1;
		
	}
	//释放资源
	private void release() {
		this.isRunning = false;
		UtilsRealease.close(dis,dos,client);
	}

	@Override
	public void run() {
		while(isRunning) {
			//先读
			String msg = this.receive();;			
			//写			
			if(!msg.equals(""))
			send(msg);
		}	
	}	
}

2.客户端 为了解决 客户端只能 先写 后读的问题,应该用多线程 并进行封装

客户端

/**
 * 客户端
 * 使用多线程 封装 : 实现多个用户发送多条消息
 * @author admin
 *
 */
public class MultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {		
		System.out.println("---------Clien---------");	
		System.out.println("请输入信息:");		
		//1.建立连接
		Socket client = new Socket("localhost",9999);
		//2.操作		
		new Thread(new Send(client)).start();
		new Thread(new Receive(client)).start();	
	}
}

发送端

/**
 * 发送
 * @author admin
 *
 */
public class Send implements Runnable{	
	private BufferedReader reader ;
	private boolean isRunning = true;
	private DataOutputStream dos;
	private Socket client;
	
	public Send(Socket client) throws IOException {
		this.client = client;
		reader = new BufferedReader(new InputStreamReader(System.in));
		isRunning = true;	
		dos =  new DataOutputStream(client.getOutputStream());
	}	
	//从控制台获取消息
	private String getConsoleInform() {
		try {
			return reader.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}
	//发送消息
	private void send(String msg) {
		try {
			dos.writeUTF(msg);
			dos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			release();
		}
	}
		
	//重写
	public void run() {
		while(isRunning) {
			String msg = getConsoleInform();
			if(!msg.equals("")) {
				send(msg);
			}
		}
	}	
	//释放资源
	public void release() {
		this.isRunning = false;
		UtilsRealease.close(dos,client);
	}
}

//接收端

/**
 * 收消息
 * @author admin
 *
 */
public class Receive implements Runnable{
	
	private boolean isRunning;
	private Socket client;
	private DataInputStream dis =  null;
	public Receive(Socket client) throws IOException {
		this.client = client;
		
		dis =  new DataInputStream(client.getInputStream());
		isRunning = true;
	}
	//收消息
	private String receive() {
		String msg ="";
		try {
			 msg = dis.readUTF();
			return msg;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return "";	
	}
	public void run() {
		while(isRunning) {
			String msg = receive();
			if(!msg.equals(""))
			System.out.println(msg);
		}
	}
	//释放资源
	private void release() {
		this.isRunning = false;
		UtilsRealease.close(dis,client);
	}
}

**

群聊

加入容器 实现群聊 容器:CopyOnWriteArrayList
**
服务端

/**
 * 服务端
 * 群聊
 * @author admin
 *
 */
public class Chat {
	
	public  static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<Channel>();
	
	public static void main(String[] args) throws IOException {	
				System.out.println("----------Server---------");			
		//1.创建
		ServerSocket server = new ServerSocket(9999);
		//2.阻塞式等待连接
		while(true){
			Socket client = server.accept();
			System.out.println("一个客户端 建立连接");
			Channel c = new Channel(client);
			all.add(c);
			//3.操作		
			new Thread(c).start();
		}		
	}	
	
	//一个客户 一个channel
	static class Channel implements Runnable{
		DataInputStream dis = null;
		DataOutputStream dos =null;
		private Socket client;
		private boolean isRunning ;
		private String name;
				
		public Channel(Socket client) throws IOException {
			this.client = client;
			dis = new DataInputStream(client.getInputStream());
			dos = new DataOutputStream(client.getOutputStream());
			isRunning = true;
			//获取名称
			this.name = receive();
			//欢迎
			this.send("欢迎您的到来");
			sendOthers(this.name+ "--来到了直播间",true); //系统消息			
		}
		
		//发消息
		private void send(String msg) {
			try {
				dos.writeUTF(msg);
				dos.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.out.println("------发——————--");
				release();
			}	
		}
		//群聊
		private void sendOthers(String msg,boolean isSys) {
			for(Channel other : all) {
				if(other == this) { //自身
					continue;
				}
				if(!isSys) {
					other.send(this.name+ "对所有人说:" + msg);
				}else {
					other.send(msg); //系统消息
				}
				
			}
		}
		//收消息
		private String receive() {
			String msg = "";
			try {
				msg = dis.readUTF();
			} catch (IOException e) {
				System.out.println("------收——————--");
				release();
			}		
			return msg;
		
		}
		//释放资源
		private void release() {
			this.isRunning = false;
			UtilsRealease.close(dis,dos,client);
			//退出
			all.remove(this);
			sendOthers(this.name + "离开了",true);
		}

		@Override
		public void run() {
			while(isRunning) {
				//先读
				String msg = this.receive();;			
				//写			
				if(!msg.equals(""))
				//send(msg);
					sendOthers(msg,false);
			}	
		}	
	}	
}

客户端
除了加了个姓名(加到构造器上) 别的无变化

私聊

自己约定个格式,然后发送
只对服务端 的 群聊发送消息的函数 进行修改就行了

		//群聊
		//私聊 :约定格式 : @XXX:msg
		private void sendOthers(String msg,boolean isSys) {
			
			boolean isPrivate = msg.startsWith("@");
			if(isPrivate) { //私聊
				int index = msg.indexOf(":");
				//获取数据
				String targetName = msg.substring(1,index);
				msg = msg.substring(index+1);
				for(Channel c : all) {
					if(c.name.equals(targetName)) { //目标对象
						c.send(this.name + "悄悄的对您说"+ msg);
					}
				}
			}else {
				for(Channel other : all) {
					if(other == this) { //自身
						continue;
					}
					if(!isSys) {
						other.send(this.name+ "对所有人说:" + msg);
						break;
					}else {
						other.send(msg); //系统消息
					}				
				}
			}
		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值