Java—网络编程

Java—网络编程1.网络编程的基本概念1.1网络的概念网络:一组相互连接的计算机,多台计算机组成,使用物理线路进行连接1.2网络连接的功能1.3网络编程的三要素1)IP地址:唯一标识网络上的每一台计算机,两台计算机之间通信的必备要素。2)端口号:计算机中应用的标号(代表一个应用程序),0-1024系统使用或保留端口,端口号占2个字节,所以有效端口0-65535.3)通信协议:通信的规则TCP,UDP4)注意:在通信协议相同的情况下,端口号才是唯一的。2.IP_端口_Scoket含义2.1IP地

大家好,又见面了,我是你们的朋友全栈君。

1.网络编程的基本概念

1.1网络的概念

网络:一组相互连接的计算机,多台计算机组成,使用物理线路进行连接
在这里插入图片描述

1.2 网络连接的功能

在这里插入图片描述

1.3 网络编程的三要素

1)IP地址:唯一标识网络上的每一台计算机,两台计算机之间通信的必备要素。
2)端口号:计算机中应用的标号(代表一个应用程序),0-1024系统使用或保留端口,端口号占2个字节,所以有效端口0-65535.
3)通信协议:通信的规则TCP,UDP
4)注意:在通信协议相同的情况下,端口号才是唯一的。
在这里插入图片描述

2.IP_端口_Scoket含义

2.1IP地址

IP地址用于标识网络上的唯一一台计算机,共32位,4个8位二进制数组成
IP地址分为:IPv4和IPv6
IPv4:“点分十进制表示法”
IPv6: “ 十六进制表示法”
在这里插入图片描述
IP 地址= 网络 ID+ 主机 ID
网络 ID :标识计算机或网络设备所有的网段
主机 ID:标识特定德主机或网络设备
在这里插入图片描述
特殊 IP 地址:

  1. 127.0.0.1:本机回环地址,用于本机测试
  2. 255.255.255.255:当前子网,一般用于当前子网广播信息

2.2 端口号

端口号:虚拟的概念,使用 0-65535 之间的整数,用于标识
不同的应用程序
每个网络程序都会至少有一个端口号
在这里插入图片描述

2.3Socket 含义

Socket 称为“套接字”,是计算机之间通信的一种约定或一种方式,通过 Socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。每一个客户端都使用一个 Socket 对象表示,服务器端使用 ServerSocket 等待客户端的连接。
在这里插入图片描述

生活案例:
如果你想写封邮件发给远方的朋友,如何写信、将信打包,属于应用层。信怎么写,怎么打包完全由我们做主;而当我们将信投入邮筒时,邮筒的那个口就是套接字,在进入套接字之后,就是传输层、网络层等(邮局、公路交管或者航线等)其它层次的工作了。我们从来不会去关心信是如何从西安发往北京的,我们只知道写好了投入邮筒就 OK了。

3.TCP 和 和 UDP 协议的区别

3.1 数据的传输

网络参考模式
(1) OSI 参考模式:开放系统互连参考模型(Open System
Interconnect)
在这里插入图片描述
(2) TCP/IP 参考模型:传输控制/网际协议 Transfer Controln
Protocol/Internet Protocol
在这里插入图片描述

3.2TCP 和 和 UDP 协议的区别

TCP(transfer control protocol)
一种面向连接(连接导向)的、可靠的、基于字节流
的运输层(Transport layer)通信协议 。
在这里插入图片描述
特点

  1. 面向连接
  2. 点到点的通信
  3. 高可靠性:三次握手
  4. 占用系统资源多、效率低

生活案例

  1. 打电话

UDP(User DatagramProtocol )
一种无连接的传输层协议,提供面向事务的简单不可靠信
息传送服务

特点:

  1. 非面向连接,传输不可靠,可能丢失
  2. 发送不管对方是否准备好,接收方收到也不确认
  3. 数据报的大小限制在 64k 内
  4. 非常简单的协议,开销小

生活案例:

  1. 发送短信 发电报
    在这里插入图片描述

4.TCP 协议数据传递细节

4.1TCP 通信原理

服务器创建 ServerSocket,在指定端口监听并处理请求
客户端创建 Socket,向服务器发送请求
在这里插入图片描述
在这里插入图片描述

5.UDP 协议数据传递细节

5.1UDP 协议数据传递细节

  1. 不需要利用 IO 流实现数据的传输
  2. 每个数据发送单元被统一封装成数据包的方式,发送方将
    数据包发送到网络中,数据包在网络中去寻找他的目的
    地。
  3. DatagramSocket:用于发送或接收数据包
  4. DatagramPacket:数据包
    在这里插入图片描述
    在这里插入图片描述

6.InetAddress 类_InetSocketAddress 类

6.1InetAddress 类

封装计算机的 IP 地址,不包含端口号

6.2InetAddress 类常用的方

在这里插入图片描述

package com.bjsxt.InetAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class TestInetAddress { 
   
    public static void main(String[] args) throws UnknownHostException { 
   
        //(1)获取InetAddress的方式
        InetAddress ia = InetAddress.getLocalHost();//本机
        System.out.println("获取主机的Ip地址:"+ia.getHostAddress());
        System.out.println("获取主机名称:"+ia.getHostName());

        //(2)根据域名得到InetAddress对象
        InetAddress ia2 = InetAddress.getByName("www.jd.com");
        System.out.println("京东服务器的IP地址:"+ia2.getHostAddress());
        System.out.println("主机名称:"+ia2.getHostName());

        //(3)根据IP地址获取一个InetAddress对象
        InetAddress ia3 = InetAddress.getByName("61.135.253.15");
        System.out.println("服务器主机IP:"+ia3.getHostAddress());
        System.out.println("主机名称:"+ia3.getHostName());
        //返回主机名称:如果 IP地址(61.135.253.15)不存在或者DNS(域名解析系统)不允许进行IP地址和域名的映射,就会直接返回一个IP地址
    }
}

在这里插入图片描述

6.3InetSocketAddress 类

此类用于实现 IP 址 套接字地址 (IP 地址+ 端口号) ,用 于socket 通信

6.4InetSocketAddress 类常用的方法

在这里插入图片描述

package com.bjsxt.InetAddress;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

public class TestInetSocketAddress { 
   
    public static void main(String[] args) throws UnknownHostException { 
   
        //创建对象
        InetSocketAddress tsa = new InetSocketAddress("localhost",9999);
        InetSocketAddress tsa2 = new InetSocketAddress("127.0.0.1",9999);
        InetSocketAddress tsa3 = new InetSocketAddress("192.168.31.113",9999);

        InetAddress ia = InetAddress.getByName("localhost");//("192.168.31.113")
        InetSocketAddress tsa4 = new InetSocketAddress(ia,9999);
        System.out.println("主机名称:"+tsa4.getHostName());
        System.out.println("主机IP地址:"+tsa4.getAddress());
        System.out.println("端口号:"+tsa4.getPort());
    }
}

在这里插入图片描述

8.URL 类

8.1URL 类

URL (Uniform Resource Locator )

统一资源定位符,由 4 部分组成:协议 、存放资源的主机
域名、端口号和资源文件名。

URL 是指向互联网 “ 资源 ” 的指针

资源可以是简单的文件或目录,也可以是对更为复杂的对
象的引用,例如对数据库或搜索引擎的查询。

8.2URL 类常用方法

在这里插入图片描述

package com.bjsxt.InetAddress;

import java.net.MalformedURLException;
import java.net.URL;

public class TestURL { 
   
    public static void main(String[] args) throws MalformedURLException { 
   
        URL url=new URL("https://www.baidu.com:80/index.html#aa?username=bjsxt&pwd=bjsxt");
        //第一部分:https://(协议)第二部分:www.baidu.com(存放资源的主机名称)第三部分::80(端口号)第四部分:index.html#aa?username=bjsxt&pwd=bjsxt(资源的文件名以及传递的参数)
        System.out.println("协议名称:"+url.getProtocol());
        System.out.println("主机名称:"+url.getHost());
        System.out.println("端口号:"+url.getPort());
        System.out.println("获取资源路径:"+url.getFile());
        System.out.println("获取资源路径:"+url.getPath());
        System.out.println("获取默认端口:"+url.getDefaultPort());
    }
}

package com.bjsxt.InetAddress;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

public class TestURL2 { 
   
    public static void main(String[] args) throws IOException, MalformedURLException { 
   
        /**网络爬虫 * (1)从网络上获取资源 www.baidu.com * (2)存储到本地 * */
        //(1)创建URL对象
        URL url = new URL("https://www.baidu.com");//主页资源
        //(2)获取字节输入流
        InputStream is = url.openStream();
        //(3)缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
        //(4)存储到本地
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("index.html"), "utf-8"));
        //(5)边读边写
        String line = null;
        while ((line = br.readLine()) != null) { 
   
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //(6)关闭流
        bw.close();
        br.close();
    }
}

生成本地index文件
在这里插入图片描述
用浏览器打开
在这里插入图片描述
右击检查源代码
在这里插入图片描述

8.3openStream() 方法

打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream

8.4基于TCP协议的Socket编程_双向通信_实现单次请求与响应

传输示意图
在这里插入图片描述
客户端
在这里插入图片描述
服务器端
在这里插入图片描述
客户端向服务器端发送字节

服务器端

package com.bjsxt.serverProject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Test { 
   
    public static void main(String[] args) throws IOException { 
   
        System.out.println("-----服务器端已启动------");
        //(1)创建ServerSocket对象
        ServerSocket server = new ServerSocket(9999);
        //(2)监听是否有客户端来请求数据
        Socket client = server.accept();
        //(3)获取输入流
        InputStream is = client.getInputStream();
        System.out.println((char)is.read());
        //(4)获取输出流
        //”收到了“
        OutputStream os = client.getOutputStream();
        os.write("收到了".getBytes());
       //(5)关闭流,关闭Socket
        if(os!=null){ 
   
            os.close();
        }
        if(is!=null){ 
   
            is.close();
        }
        if(client!=null){ 
   
            client.close();
        }
    }
}

客户端

package com.bjsxt.clientProject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Test { 
   
    public static void main(String[] args) throws IOException { 
   
        //(1)创建Socket对象
        Socket client=new Socket("127.0.0.1", 9999);
        //(2)获取输出流
        OutputStream os=client.getOutputStream();
        os.write('a');

        //(3)获取输入流
        InputStream is=client.getInputStream();
        byte [] buf=new byte[1024];//中转站,缓冲区
        int len=0;//读到的字节的个数
        while((len=is.read(buf))!=-1){ 
   
            System.out.println(new String(buf,0,len));
        }
        //(4)关闭流
        if(is!=null){ 
   
            is.close();
        }
        if(os!=null){ 
   
            os.close();
        }
        if(client!=null){ 
   
            client.close();
        }
    }
}


先启动服务器端,再启动客户端

客户机向服务器发送字符串

服务器端

package com.bjsxt.serverProject;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServer { 
   
    public static void main(String[] args) throws IOException, IOException { 
   
        System.out.println("-------------服务器端已启动----------------");
        //(1)创建ServerSocket对象
        ServerSocket server=new ServerSocket(9999);
        //(2)监听是否有客户端来请求连接
        Socket client=server.accept();
        //(3) 获取输入流
        DataInputStream dis=new DataInputStream(client.getInputStream());
        System.out.println(dis.readUTF());

        //(4)获取输出流
        //"收到了"
        DataOutputStream dos=new DataOutputStream(client.getOutputStream());
        dos.writeUTF("收到了");
        //(5)关闭流,关闭Socket
        if(dos!=null){ 
   
            dos.close();
        }
        if(dis!=null){ 
   
            dis.close();
        }
        if(client!=null){ 
   
            client.close();
        }
    }
}

客户机端

package com.bjsxt.clientProject;

import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class TestClient { 
   
    public static void main(String[] args) throws IOException { 
   
        //(1)创建Socket对象
        Socket client=new Socket("127.0.0.1", 9999);
        //(2)获取输出流
        DataOutputStream dos=new DataOutputStream(client.getOutputStream());
        dos.writeUTF("helloworld");
        //(3)获取输入流
        DataInputStream dis=new DataInputStream(client.getInputStream());
        System.out.println(dis.readUTF());
        //(4)关闭流
        if(dis!=null){ 
   
            dis.close();
        }
        if(dos!=null){ 
   
            dos.close();
        }
        if(client!=null){ 
   
            client.close();
        }
    }
}

先启动服务器端再启动客户机端

9.基于TCP协议的Socket编程_双向通信_实现模拟用户登录

9.1 双向通信_用户登录示意图

在这里插入图片描述
clientLoginProject

Client.java

package com.bjsxt.entity;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client { 
   
	public static void main(String[] args) throws IOException { 
   
		//(1)创建Socket对象,用于连接服务器
		Socket client=new Socket("localhost", 8888);
		//(2)获取输出流 (对象流)
		ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
		//(3)创建User对象
		          //调用获取用户对象的方法
		User u=getUser();//new User("bjsxt", "bjsxt");
		//(4)User对象发送到服务器
		oos.writeObject(u);
		
		//(5)获取输入流(数据流)
		DataInputStream dis=new DataInputStream(client.getInputStream());
		System.out.println(dis.readUTF());
		//(6)关闭流
		if(dis!=null){ 
   
			dis.close();
		}
		if(oos!=null){ 
   
			oos.close();
		}
		if(client!=null){ 
   
			client.close();
		}
	}
	//获取用户对象的方法
	public static User getUser(){ 
   
		Scanner input=new Scanner(System.in);
		System.out.println("请输入用户名:");
		String userName=input.next();
		System.out.println("请输入密码:");
		String password=input.next();
		//封装成User对象
		return new User(userName,password);
	}
}

User.java

package com.bjsxt.entity;

import java.io.Serializable;

public class User implements Serializable { 
   //用于封装用户名和密码,
	
	/** * */
	private static final long serialVersionUID = -2618388865354437739L;
	private String userName;
	private String password;
	public String getUserName() { 
   
		return userName;
	}
	public void setUserName(String userName) { 
   
		this.userName = userName;
	}
	public String getPassword() { 
   
		return password;
	}
	public void setPassword(String password) { 
   
		this.password = password;
	}
	public User(String userName, String password) { 
   
		super();
		this.userName = userName;
		this.password = password;
	}
	public User() { 
   
		super();
	}
	
}

serverLoginProject

Server.java

package com.bjsxt.server;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

import com.bjsxt.entity.User;
import com.bjsxt.thread.ServerThread;

public class Server { 
   
	public static void main(String[] args) throws IOException, ClassNotFoundException { 
   
		System.out.println("----------------------服务器端已启动---------------------");
		//(1)创建ServerSocket对象
		ServerSocket server=new ServerSocket(8888);
		
		while(true){ 
   
			Socket socket=server.accept();
			//创建线程类的对象,并启动线程
			ServerThread st=new ServerThread(socket);
			//启动线程
			new Thread(st).start();
		}
	}
}

User.java

package com.bjsxt.entity;

import java.io.Serializable;

public class User implements Serializable { 
   //用于封装用户名和密码,
	
	/** * */
	private static final long serialVersionUID = -2618388865354437739L;
	private String userName;
	private String password;
	public String getUserName() { 
   
		return userName;
	}
	public void setUserName(String userName) { 
   
		this.userName = userName;
	}
	public String getPassword() { 
   
		return password;
	}
	public void setPassword(String password) { 
   
		this.password = password;
	}
	public User(String userName, String password) { 
   
		super();
		this.userName = userName;
		this.password = password;
	}
	public User() { 
   
		super();
	}
	
}

ServerThread.java

package com.bjsxt.thread;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;

import com.bjsxt.entity.User;

public class ServerThread implements Runnable{ 
   
	private Socket socket;//成员变量
	public ServerThread(Socket socket){ 
   
		this.socket=socket;
	}
	@Override
	public void run() { 
   
		System.out.println(Thread.currentThread().getName()+"请求登录");
		//(2)获取输入流--(对象流)
		ObjectInputStream ois=null;
		//(4)获取输出流(数据流)
		DataOutputStream dos=null;
		try { 
   
			ois = new ObjectInputStream(socket.getInputStream());
					User user=(User) ois.readObject();
					
					System.out.println(socket.getInetAddress().getHostAddress()+"请求登录:用户名"+user.getUserName()+"\t密码:"+user.getPassword());
					String str="";
					//(3)对用户名和密码进行验证
					if("bjsxt".equals(user.getUserName())&&"bjsxt".equals(user.getPassword())){ 
   
						str="登录成功";
					}else{ 
   
						str="对不起,账号号密码不正确";
					}
					dos = new DataOutputStream(socket.getOutputStream());
					dos.writeUTF(str);
		} catch (ClassNotFoundException e) { 
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) { 
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{ 
   
				//(5)关闭流
				if(dos!=null){ 
   
					try { 
   
						dos.close();
					} catch (IOException e) { 
   
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(ois!=null){ 
   
					try { 
   
						ois.close();
					} catch (IOException e) { 
   
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(socket!=null){ 
   
					try { 
   
						socket.close();
					} catch (IOException e) { 
   
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
		}
		
	}

}

10. 基于TCP协议的Socket编程_聊天室_客户端多线程

10.1单次聊天的缺点

只能客户端现发送数据,然后才能接受数据,如果不发就收不到,(接收和发送是在一个线程中实现的)不符合实际情况。

10.2解决方案

(1)多次聊天可以使用循环来解决
(2)先发后收的问题可以使用线程来解决,一个接受数据的线程,一个发送数据的线程。

10.3最终实现

单个客户端与服务器端多次通信
在这里插入图片描述
单次聊天客户端与服务器端

ChatClient

Client.java

package com.bjsxt.chat.client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Client { 
   

	public static void main(String[] args) throws IOException { 
   
		//(1)创建Socket对象
		Socket client=new Socket("localhost",9999);
		//(2)从键盘获取数据
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		//(3)获取输出流
		DataOutputStream dos=new DataOutputStream(client.getOutputStream());
		//(4)获取输入流
		DataInputStream dis=new DataInputStream(client.getInputStream());
		
		//从键盘获取数据
		String str=br.readLine();
		dos.writeUTF(str);//向服务器端发送数据
		
		System.out.println(dis.readUTF());//接收服务器端的数据
		
	   
	}
}

CloseUtil.java

package com.bjsxt.chat.client;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

chatServer

Server.java

package com.bjsxt.chat.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server { 
   
	
	public static void main(String[] args) throws IOException { 
   
		System.out.println("----------------服务器端已开启---------------------");
		//(1)创建ServerSocket对象
		ServerSocket server=new ServerSocket(9999);
		
		//(2)监听客户端是否有客户端连接
		Socket socket=server.accept();
		
		//获取输入流
		DataInputStream dis=new DataInputStream(socket.getInputStream());
		//获取输出流
		DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
		
		String str=dis.readUTF();
		System.out.println("客户端发送了:"+str);
		
		dos.writeUTF("服务器端收到了:"+str);
		
		//(5)关闭流
		CloseUtil.closeAll(dos,dis,socket);
	}
}

CloseUtil.java

package com.bjsxt.chat.server;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

客户端多线程聊天
chatClient

Client.java

package com.bjsxt.chat.client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Client { 
   
	public static void main(String[] args) throws IOException { 
   
		//(1)创建Socket对象
		Socket client=new Socket("localhost",9999);
		
		//创建发送的线程类对象
		Send send=new Send(client);
		//创建接收的线程类对象
		Receive receive=new Receive(client);
		//创建Thread类对象并启动线程
		new Thread(send).start();
		new Thread(receive).start();
	
	}
}

Receive.java

package com.bjsxt.chat.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

public class Receive implements Runnable { 
   
	//用于接收数据的数据流
	private DataInputStream dis;
	private boolean flag=true;
	public Receive(Socket client){ 
   
		try { 
   
			dis=new DataInputStream(client.getInputStream());
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis,client);
		}
	}
	private String getMessage(){ 
   
		String str="";
		try { 
   
			str = dis.readUTF();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis);
		}
		return str;
	}
	@Override
	public void run() { 
   
		while(flag){ 
   
			System.out.println(this.getMessage());
		}
	}

}

CloseUtil.java

package com.bjsxt.chat.client;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

Send.java

package com.bjsxt.chat.client;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Send implements Runnable { 
   
	//(2)从键盘获取数据
	private BufferedReader  br;
			//发送数据的数据流
	private DataOutputStream  dos;
	private boolean flag=true;//默认为true
	
	public Send(){ 
   
		br=new BufferedReader(new InputStreamReader(System.in));
	}
	public Send(Socket client){ 
   
		this();//调用本类的无参构造方法
		try { 
   
			dos=new DataOutputStream(client.getOutputStream());
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dos,client);
		}
	}
	
	private String getMessage(){ 
   
		String str="";
		try { 
   
			str = br.readLine();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(br);
		}
		return str;
	}
	private void send(String str){ 
   
		try { 
   
			dos.writeUTF(str);
			dos.flush();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dos);
		}
	}
	@Override
	public void run() { 
   
		while(flag){ 
   
			//调用发送信息的方法
			this.send(getMessage());
		}
	}

}

chatServer

Server.java

package com.bjsxt.chat.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server { 
   
	public static void main(String[] args) throws IOException { 
   
		System.out.println("----------------服务器端已开启---------------------");
		// (1)创建ServerSocket对象
		ServerSocket server = new ServerSocket(9999);
		// (2)监听客户端是否有客户端连接
		Socket socket = server.accept();

		// (3)获取输入流接收数据
		DataInputStream dis = new DataInputStream(socket.getInputStream());
		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		while(true){ 
   
			String str = dis.readUTF();
			System.out.println("客户端发送的数据为:-->" + str);
	
			// (4)获取输出流响应客户端的请求
			dos.writeUTF("服务器端收到了:" + str);
		}

		// (5)关闭流
		//CloseUtil.closeAll(dos, dis, socket);
	}
}

CloseUtil.java

package com.bjsxt.chat.server;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

11.基于TCP协议的Socket编程_聊天室_群聊

在这里插入图片描述
chatClient

Client.java

package com.bjsxt.chat.client;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Client { 
   
	public static void main(String[] args) throws IOException { 
   
		//(1)创建Socket对象
		Socket client=new Socket("localhost",9999);
		
		//创建发送的线程类对象
		Send send=new Send(client);
		//创建接收的线程类对象
		Receive receive=new Receive(client);
		//创建Thread类对象并启动线程
		new Thread(send).start();
		new Thread(receive).start();
	
	}
}

CloseUtil.java

package com.bjsxt.chat.client;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

Receive.java

package com.bjsxt.chat.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

public class Receive implements Runnable { 
   
	//用于接收数据的数据流
	private DataInputStream dis;
	private boolean flag=true;
	public Receive(Socket client){ 
   
		try { 
   
			dis=new DataInputStream(client.getInputStream());
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis,client);
		}
	}
	private String getMessage(){ 
   
		String str="";
		try { 
   
			str = dis.readUTF();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis);
		}
		return str;
	}
	@Override
	public void run() { 
   
		while(flag){ 
   
			System.out.println(this.getMessage());
		}
	}

}

Send.java

package com.bjsxt.chat.client;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Send implements Runnable { 
   
	//(2)从键盘获取数据
	private BufferedReader  br;
			//发送数据的数据流
	private DataOutputStream  dos;
	private boolean flag=true;//默认为true
	
	public Send(){ 
   
		br=new BufferedReader(new InputStreamReader(System.in));
	}
	public Send(Socket client){ 
   
		this();//调用本类的无参构造方法
		try { 
   
			dos=new DataOutputStream(client.getOutputStream());
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dos,client);
		}
	}
	
	private String getMessage(){ 
   
		String str="";
		try { 
   
			str = br.readLine();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(br);
		}
		return str;
	}
	private void send(String str){ 
   
		try { 
   
			dos.writeUTF(str);
			dos.flush();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dos);
		}
	}
	@Override
	public void run() { 
   
		while(flag){ 
   
			//调用发送信息的方法
			this.send(getMessage());
		}
	}

}

chatServer

Server.java

package com.bjsxt.chat.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server { 
   
	//创建集合对象,存储每一个连接进来的客户端
	public static List<MyChannel> list=new ArrayList<MyChannel>();
	public static void main(String[] args) throws IOException { 
   
		System.out.println("----------------服务器端已开启---------------------");
		// (1)创建ServerSocket对象
		ServerSocket server = new ServerSocket(9999);
		// (2)监听客户端是否有客户端连接
		while(true){ 
   
			Socket socket = server.accept();
			//创建线程类的对象
			MyChannel channel=new MyChannel(socket);
			//添加到集合中
			list.add(channel);
			
			//启动线程
			new Thread(channel).start();;
		}
		


		// (5)关闭流
		//CloseUtil.closeAll(dos, dis, socket);
	}
}

CloseUtil.java

package com.bjsxt.chat.server;

import java.io.Closeable;
import java.io.IOException;

public class CloseUtil { 
   
	public static void closeAll(Closeable... able){ 
   
		for (Closeable c : able) { 
   
			if (c!=null) { 
   
				try { 
   
					c.close();
				} catch (IOException e) { 
   
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

MyChannel.java

package com.bjsxt.chat.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.List;

/* * 每一个客户端都是条道路 * 1.输入流 * 2.输出流 * 3.接收数据 *4.发送数据 */
public class MyChannel implements Runnable{ 
   
	private DataInputStream dis;
	private DataOutputStream dos;
	private boolean flag=true;
	public MyChannel(Socket client){ 
   
		try { 
   
			dis=new DataInputStream(client.getInputStream());
			dos=new DataOutputStream(client.getOutputStream());
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis,dos);
		}
	}
	//接收数据的方法
	private String receive(){ 
   
		String str="";
		try { 
   
			str=dis.readUTF();
		} catch (IOException e) { 
   
			flag=false;
			CloseUtil.closeAll(dis,dos);
			Server.list.remove(this);
		}
		return str;
	}
	//发送数据的方法
	private void send(String str){ 
   
		if (str!=null&&str.length()!=0) { 
   
			try { 
   
				dos.writeUTF(str);
				dos.flush();
			} catch (IOException e) { 
   
				flag=false;
				CloseUtil.closeAll(dos,dis);
				Server.list.remove(this);
			}
			
		}
	}
	//转发的方法
	private void sendOther(){ 
   
		String str=this.receive();
		List<MyChannel> list=Server.list;
		for (MyChannel other : list) { 
   
			if (other==this) { 
   
				continue;//不发给自己
			}
			other.send(str);//发送数组
		}
	}
	@Override
	public void run() { 
   
		while(flag){ 
   
			//调用发送数据的方法
			//this.send(receive());
			sendOther();
		}
	}
	

}

12.UDP通信_DatagramSoclet实现_客户咨询

1)不需要利用IO流实现数据的传输
2)每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送到网络中,数据包在网络中去寻找他的目的地。
3)DatagramSocket:用于发送或接收数据包
4)DatagramPacket:数据包

发送方
UDPProject_1

Test1.java

package com.bjsxt.udp;

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

public class Test1 { 
   
	//一次双向通信
	/**一发 * 一收 * @throws IOException */
	public static void main(String[] args) throws IOException { 
   
		System.out.println("咨询者");
		//创建DatagramSocket对象
		DatagramSocket ds=new DatagramSocket(8888);//本应用程序的端口
		//准备要发送的数据
		byte[] buf="helloworld".getBytes();
		//创建数据报对象
		                            //发送的数据, 发多少,发到哪台主机,主机程序使用的端口
		DatagramPacket dp=new DatagramPacket(buf, buf.length, InetAddress.getByName("localhost"), 9999);
		
		//发送
		ds.send(dp);
		
		/**接收数据*/
		byte [] buf2=new byte[1024];
		DatagramPacket dp2=new DatagramPacket(buf2, buf2.length);
		// 借助String的构造方法查看
		ds.receive(dp2);
		String str=new String(dp2.getData(),0,dp2.getLength());
		System.out.println("客服说:"+str);
		
		ds.close();
	}
}

Test2.java

package com.bjsxt.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Test2 { 
   
	//一次双向通信
	/**一发 * 一收 * @throws IOException */
	public static void main(String[] args) throws IOException { 
   
		System.out.println("咨询者");
		Scanner input=new Scanner(System.in);
		//创建DatagramSocket对象
		DatagramSocket ds=new DatagramSocket(8888);//本应用程序的端口
		while(true){ 
   
			//准备要发送的数据
			String s=input.next();
			byte[] buf=s.getBytes();
			//创建数据报对象
			                            //发送的数据, 发多少,发到哪台主机,主机程序使用的端口
			DatagramPacket dp=new DatagramPacket(buf, buf.length, InetAddress.getByName("localhost"), 9999);
			
			//发送
			ds.send(dp);
			
			/**接收数据*/
			byte [] buf2=new byte[1024];
			DatagramPacket dp2=new DatagramPacket(buf2, buf2.length);
			// 借助String的构造方法查看
			ds.receive(dp2);
			String str=new String(dp2.getData(),0,dp2.getLength());
			System.out.println("客服说:"+str);
			
			if("bye".equals(s)){ 
   
				break;
			}
		}
		ds.close();
	}
}

接收方

UDPProject_2

Test1.java

package com.bjsxt.udp;

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

public class Test1 { 
   
	//接收方
			/** 一收, * 一发 * @throws IOException */
	public static void main(String[] args) throws IOException { 
   
		System.out.println("客服人员");
		DatagramSocket ds=new DatagramSocket(9999);
		//准 备接收数据
		byte [] buf=new byte[1024];
		//准 备数据报接收
		DatagramPacket dp=new DatagramPacket(buf, buf.length);
		
		//接收
		ds.receive(dp);
		
		//查看接收到的数据
		String str=new String(dp.getData(),0,dp.getLength());
		System.out.println("客户说:"+str);
		
		
		/**回复数据*/
		byte [] buf2="welcome to beijing".getBytes();
		DatagramPacket dp2=new DatagramPacket(buf2, buf2.length, dp.getAddress(), dp.getPort());
		ds.send(dp2);
		//关闭
		ds.close();
		
			
	}
}

Test2.java

package com.bjsxt.udp;

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

public class Test2 { 
   
	//接收方
			/** 一收, * 一发 * @throws IOException */
	public static void main(String[] args) throws IOException { 
   
		Scanner input=new Scanner(System.in);
		System.out.println("客服人员");
		DatagramSocket ds=new DatagramSocket(9999);
		while(true){ 
   
			//准 备接收数据
			byte [] buf=new byte[1024];
			//准 备数据报接收
			DatagramPacket dp=new DatagramPacket(buf, buf.length);
			
			//接收
			ds.receive(dp);
			
			//查看接收到的数据
			String str=new String(dp.getData(),0,dp.getLength());
			System.out.println("客户说:"+str);
			
			String s=input.next();
			/**回复数据*/
			byte [] buf2=s.getBytes();
			DatagramPacket dp2=new DatagramPacket(buf2, buf2.length, dp.getAddress(), dp.getPort());
			ds.send(dp2);
			if("bye".equals(s)){ 
   
				break;
			}
		}
		//关闭
			
		ds.close();
		
			
	}
}

Java—XML技术

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156937.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JDK安装、java环境配置

    JDK安装、java环境配置

    2021年10月23日
    36
  • 字体格式及缩放不要设置怎么做_退库单格式

    字体格式及缩放不要设置怎么做_退库单格式使用libyuv库在Linux下对NV12格式进行缩放

    2022年9月24日
    0
  • centos创建samba共享_安卓samba服务器

    centos创建samba共享_安卓samba服务器对公司的不同部门建立不同的文件共享,不同的用户访问同一个共享目录具有不同的权限.

    2022年9月15日
    0
  • Voliate

    Voliate1、voliate的理论作用:A、保证可见性B、保证指令不重新排2、可见性原理:a.保证写后的数据马上回写到系统内存b。根据缓存一致性协议,保证写后,数据在总线声明为过期,其他已经读取过这个变量的处理器会通过嗅探技术,发现自己的数据内存被修改,声明无效,如果要修改,则会重新去读取,但是,如果不修改,则不会去读取c.不能保证原子性代码:while(i==1){i++;}…

    2022年4月28日
    69
  • whl文件安装方法

    whl文件安装方法   whl格式本质上是一个压缩包,里面包含了py文件,以及经过编译的pyd文件。使得可以在不具备编译环境的情况下,选择合适自己的python环境进行安装问题描述:whl下载了后不会安装解决方法:1.把下载的文件拖到桌面2.进入cmd命令行3.使用cd进入whl文件属性标识的目录)(红色框)4.使用“pipinstall文件名”安装下载的文件(绿色框)5.安装完成…

    2022年5月30日
    50
  • kafka的使用场景举例_kafka一般用来做什么

    kafka的使用场景举例_kafka一般用来做什么关于消息队列的使用一、消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ二、消息队列应用场景以下介绍消息队列在实际应用中常用的使用场景。异步处理,应用解耦,流量削锋和消息通讯四个场景。2.1异步…

    2022年10月15日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号