Java 【网络编程】学习笔记
程序员文章站
2022-07-11 20:58:46
...
网络编程
IP
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* InetAddress: 多个静态方法
* 1.getLocalHost:本机
* 2.getByName:根据域名DNS || IP地址 ———>IP
*
* 两个成员方法:
* 1.getHostAddress:返回地址
* 2.getHostName:返回计算机名
*/
public class IPTest {
public static void main(String[] args) throws UnknownHostException {
//使用getLocalHost方法创建InetAddress对象 本机
InetAddress address = InetAddress.getLocalHost();
System.out.println(address.getHostAddress());
System.out.println(address.getHostName());
//根据域名得到InetAddress对象
address = InetAddress.getByName("www.163.com");
System.out.println(address.getHostAddress());
System.out.println(address.getHostName());
//根据IP得到InetAddress对象
address = InetAddress.getByName("121.22.230.62");
System.out.println(address.getHostAddress());
System.out.println(address.getHostName());//输出的IP不是域名,如果这个IP地址不存在或DNS服务器不允许进行IP地址和域名的映射,getHostName方法就直接返回这个IP地址
}
}
端口
-
查看所有端口: netstat-ano•
-
查看指定端口: netstat-aon|findstr"808"
-
查看指定进程: tasklist|findstr"808"
-
查看具体程序:使用任务管理器查看 PID
import java.net.InetSocketAddress;
/**
* 端口:
* 1.区分软件
* 2. 2个字节 0-65535 UDP TCP
* 3.同一个协议端口不能冲突
* 4.定义端口越大越好
* InetSocketAddress
* 1.构造器
* new InetSocketAddress(地址|域名,8080);
* 2.方法
* getAddress()
* getPort()
* getHostName()
*/
public class PortTest {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress1 = new InetSocketAddress("localhost",9000);
System.out.println(socketAddress.getHostName());
System.out.println(socketAddress1.getAddress());
System.out.println(socketAddress1.getPort());
}
}
URL
import java.net.MalformedURLException;
import java.net.URL;
/**
* 统一资源定位器 互联网三大基石之一(HTML http),区分资源
* 1.协议
* 2.域名或计算机名
* 3.端口 :默认80
* 4.请求资源
* http:||www.baidu.com:80|index.html?uname=shsxt&age=18#a
*/
public class URLTest {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://www.csdn.net");
//获取四个值
System.out.println("协议"+url.getProtocol());
System.out.println("域名|IP"+url.getHost());
System.out.println("请求资源"+url.getFile());
System.out.println("请求资源"+url.getPath());
System.out.println("端口"+url.getPort());
//参数
System.out.println("参数"+url.getQuery());
//锚点
System.out.println("锚点"+url.getRef());
}
}
爬虫原理
import java.io.*;
import java.net.URL;
/**
* 网络爬虫的原理
*/
public class SpiderTest01 {
public static void main(String[] args) throws IOException {
//获取URL
URL url = new URL("https://www.csdn.net/");
//下载资源
InputStream inputStream = url.openStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
String msg =null;
while (null!=(msg = bufferedReader.readLine())){
System.out.println(msg);
}
bufferedReader.close();
}
}
/**
* 网络爬虫的原理+模拟浏览器
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SpiderTest02 {
public static void main(String[] args) throws IOException {
//获取URL
URL url = new URL("https://www.csdn.net/");
//下载资源
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("......");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
String msg =null;
while (null!=(msg = bufferedReader.readLine())){
System.out.println(msg);
}
bufferedReader.close();
}
}
UDP网络编程
基本步骤
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
/**
* 基本流程:
* 发送端
* 1.使用DatagramSocket创建发送端 (指定端口)
* 2.准备数据 一定转成字节数组
* 3.封装成DatagramPacket 包裹 需要指定目的地
* 4.发送包裹 send(DatagramPacket p)
* 5.释放资源
*/
public class UDPClient {
public static void main(String[] args) throws Exception{
System.out.println("发送方启动中......");
DatagramSocket client = new DatagramSocket(8888);
String data = "上海尚学堂";
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",9999));
client.send(packet);
client.close();
}
}
/**
* 基本流程:
* 接收端
* 1.使用DatagramSocket创建接收端 (指定端口)
* 2.准备容器 封装成DatagramPacket 包裹
* 3.阻塞式接受包裹 recieve(DatagramPacket p)
* 4.分析数据
* byte[] getData()
* getLength()
*/
public class UDPServer {
public static void main(String[] args) throws IOException {
System.out.println("接收方启动中......");
DatagramSocket server = new DatagramSocket(6666);
byte[] container = new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
server.receive(packet);
byte[] datas = packet.getData();
int len = packet.getLength();
System.out.println(new String(datas,0,len));
}
}
上传文件
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* 基本流程:
* 发送端
* 1.使用DatagramSocket创建发送端 (指定端口)
* 2.准备数据 一定转成字节数组
* 3.封装成DatagramPacket 包裹 需要指定目的地
* 4.发送包裹 send(DatagramPacket p)
* 5.释放资源
*/
public class UDPTypeClient {
public static void main(String[] args) throws Exception{
System.out.println("发送方启动中......");
DatagramSocket client = new DatagramSocket(8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
dos.writeUTF("编码辛酸泪");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas = baos.toByteArray();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
client.send(packet);
client.close();
}
}
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 基本流程:
* 接收端
* 1.使用DatagramSocket创建接收端 (指定端口)
* 2.准备容器 封装成DatagramPacket 包裹
* 3.阻塞式接受包裹 recieve(DatagramPacket p)
* 4.分析数据 将字节数组还原为对应的类型
* byte[] getData()
* getLength()
*/
public class UDPTypeServer {
public static void main(String[] args) throws IOException {
System.out.println("接收方启动中......");
DatagramSocket server = new DatagramSocket(6666);
byte[] container = new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
server.receive(packet);
byte[] datas = packet.getData();
int len = packet.getLength();
DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dataInputStream.readUTF();
int age = dataInputStream.readInt();
boolean flag = dataInputStream.readBoolean();
char ch = dataInputStream.readChar();
System.out.println(msg+"-->"+flag);
server.close();
}
}
案例:在线咨询
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* 发送端 :使用面向对象封装
*/
public class TalkSend implements Runnable{
private DatagramSocket client;
private BufferedReader reader;
private String toIp;
private int toPort;
public TalkSend(int port,String toIp,int toPort) {
this.toIp = toIp;
this.toPort = toPort;
try {
client = new DatagramSocket(port);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(true){
String data = null;
try {
data = reader.readLine();
byte []datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
client.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
client.close();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.regex.Pattern;
/**
* 接收端:使用面向对象封装
*/
public class TalkRecieve implements Runnable{
private DatagramSocket server;
private String from;
public TalkRecieve(int port,String from){
this.from = from;
try {
server = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
byte[] container = new byte[1024 * 60];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
try {
server.receive(packet);
byte[] datas = packet.getData();
int len = packet.getLength();
String data = new String(datas, 0, len);
System.out.println(from+":"+data);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 加入多线程,实现双向交流 模拟在线咨询
*/
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7777,"localhost",9999)).start();//发送
new Thread(new TalkRecieve(8888,"老师")).start();
}
}
/**
* 加入多线程,实现双向交流 模拟在线咨询
*/
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkRecieve(9999,"学生")).start();//接收
new Thread(new TalkSend(5555,"localhost",8888)).start();
}
}
TCP网络编程
基本步骤
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 熟悉流程
* 创建服务器
* 1.指定端口 使用ServerSocket 创建服务器
* 2.阻塞式等待连接 accept
* 3.操作:输入输出流操作
* 4.释放资源
*/
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("-----创建服务器-----");
//1.指定端口 使用ServerSocket 创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:输入输出流操作
DataInputStream dis = new DataInputStream(client.getInputStream());
String data = dis.readUTF();
System.out.println(data);
//4.释放资源
dis.close();
client.close();
server.close();
}
}
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 熟悉流程
* 创建客户端
* 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
* 2.操作: 输入输出流操作
* 3.释放资源
*/
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
//1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
Socket client = new Socket("localhost",8888);
//2.操作: 输入输出流操作
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
String data = "hello";
dos.writeUTF(data);
dos.flush();
//3.释放资源
dos.close();
client.close();
}
}
单向登录
/**
* 模拟登录 单向
* 创建客户端
* 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
* 2.操作: 输入输出流操作
* 3.释放资源
*/
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创建客户端 + 服务的地址和端口
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();
}
}
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 模拟登录 单向
* 创建服务器
* 1.指定端口 使用ServerSocket 创建服务器
* 2.阻塞式等待连接 accept
* 3.操作:输入输出流操作
* 4.释放资源
*/
public class LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("-----创建服务器-----");
//1.指定端口 使用ServerSocket 创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:输入输出流操作
DataInputStream dis = new DataInputStream(client.getInputStream());
String datas= dis.readUTF();
//分析
String []datasArray = datas.split("&");
for (String info:datasArray){
String[] userinfo = info.split("=");
System.out.println(userinfo[0]+"-->"+userinfo[1]);
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();
}
}
双向登录
import java.io.*;
import java.net.Socket;
/**
* 模拟登录 双向
* 创建客户端
* 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
* 2.操作: 输入输出流操作
* 3.释放资源
*/
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创建客户端 + 服务的地址和端口
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();
client.close();
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 模拟登录 双向
* 创建服务器
* 1.指定端口 使用ServerSocket 创建服务器
* 2.阻塞式等待连接 accept
* 3.操作:输入输出流操作
* 4.释放资源
*/
public class LoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("-----创建服务器-----");
//1.指定端口 使用ServerSocket 创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:输入输出流操作
DataInputStream dis = new DataInputStream(client.getInputStream());
String datas= dis.readUTF();
String uname = "";
String upwd ="";
//分析
String []datasArray = datas.split("&");
for (String info:datasArray){
String[] userinfo = info.split("=");
System.out.println(userinfo[0]+"-->"+userinfo[1]);
//分析
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("lwz") && upwd.equals("123456")){
dos.writeUTF("登录成功,欢迎回来");
}else{
dos.writeUTF("用户名或密码错误");
}
dos.flush();
//4.释放资源
dis.close();
client.close();
}
}
文件上传
import java.io.*;
import java.net.Socket;
/**
* 上传文件
* 创建客户端
* 1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
* 2.操作: 输入输出流操作
* 3.释放资源
*/
public class FileClient {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
//1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
Socket client = new Socket("localhost",8888);
//2.操作: 输入输出流操作 拷贝上传
InputStream is = new BufferedInputStream(new FileInputStream("E:\\Download\\ThreadStudy\\lantian.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();
os.close();
is.close();
//3.释放资源
client.close();
}
}
/**
* 存储文件
* 创建服务器
* 1.指定端口 使用ServerSocket 创建服务器
* 2.阻塞式等待连接 accept
* 3.操作:输入输出流操作
* 4.释放资源
*/
public class FileServer {
public static void main(String[] args) throws IOException {
System.out.println("-----创建服务器-----");
//1.指定端口 使用ServerSocket 创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
//3.操作:输入输出流操作
InputStream is = new BufferedInputStream(client.getInputStream());
OutputStream os = new BufferedOutputStream(new FileOutputStream("src/tcp.png"));
byte []flush = new byte[1024];
int len = -1;
while ((len=is.read(flush))!=-1){
os.write(flush,0,len);
}
os.flush();
os.close();
is.close();
//4.释放资源
client.close();
server.close();
}
}
多用户登录
import java.io.*;
import java.net.Socket;
public class LoginMultiClient {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
Socket client = new Socket("localhost",8888);
new Send(client).send();
new Recieve(client).recieve();
client.close();
}
static class Send{
private Socket client;
private BufferedReader br;
private DataOutputStream dos;
private String msg;
public Send(Socket client){
try {
this.client = client;
br = new BufferedReader(new InputStreamReader(System.in));
this.msg = init();
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private String init(){
try {
System.out.println("请输入用户名");
String uname = br.readLine();
System.out.println("请输入密码");
String upwd = br.readLine();
return "uname=" + uname + "&pwd=" + upwd;
}catch (IOException e){
e.printStackTrace();
}
return "";
}
public void send(){
try {
dos.writeUTF(this.msg);
dos.flush();
}catch (IOException e){
e.printStackTrace();
}
}
}
static class Recieve{
private Socket client;
private DataInputStream dis;
public Recieve(Socket client){
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
}catch (IOException e){
e.printStackTrace();
}
}
public void recieve(){
String response;
try {
response = dis.readUTF();
System.out.println(response);
}catch (IOException e){
e.printStackTrace();
}
}
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginMultiServer{
public static void main(String[] args) throws IOException {
System.out.println("-----server-----");
ServerSocket server = new ServerSocket(8888);
boolean isRuning = true;
while (isRuning){
Socket socket = server.accept();
System.out.println("一个客户端建立了连接");
new Thread(new Channel(socket)).start();
}
server.close();
}
static class Channel implements Runnable{
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos;
public Channel(Socket client){
this.socket = client;
try {
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
}catch (IOException e){
e.printStackTrace();
release();
}
}
public String recieve(){
String datas = "";
try {
datas = dis.readUTF();
}catch (IOException e){
e.printStackTrace();
}
return datas;
}
public void send(String msg){
try {
dos.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
public void release(){
if (null!=dos){
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null!=dis){
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null!=dos){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
String datas = recieve();
String []dataArray = datas.split("&");
String uname = null;
String upwd = null;
for (String info:dataArray) {
String[] userinfo = info.split("=");
if ("uname".equals(userinfo[0])) {
uname = userinfo[1];
System.out.println("用户名:" + uname);
} else if ("pwd".equals(userinfo[0])) {
upwd = userinfo[1];
System.out.println("密码:" + upwd);
}
}
if (uname.equals("zs")&& upwd.equals("123")){
send("登录成功,欢迎回来");
}else {
send("用户名或密码错误");
}
release();
}
}
}
手写聊天室
基础简易版
import java.io.*;
import java.net.Socket;
/**
* 在线聊天室: 客户端
* 目标: 实现一个客户可以正常收发多条消息
*/
public class TMultiClient {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
//1.建立连接: 使用Socket创建客户端 + 服务的地址和端口
Socket client = new Socket("localhost",8888);
//2.客户端发送消息
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
DataInputStream dis = new DataInputStream(client.getInputStream());
boolean isRunning = true;
while (isRunning) {
String msg = console.readLine();
dos.writeUTF(msg);
dos.flush();
//3.获取消息
msg = dis.readUTF();
System.out.println(msg);
}
//4.释放资源
dos.close();
dis.close();
client.close();
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 在线聊天室 :服务端
* 目标:实现一个客户可以正常收发多条信息
* 问题:其他客户必须等待之前的客户退出,才能继续 排队
* 问题:
* 1.代码不好维护
* 2.哭护短读写没有分开 必须先写后读
*/
public class TMultiChat {
public static void main(String[] args) throws IOException {
System.out.println("-----创建服务器-----");
//1.指定端口 使用ServerSocket 创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
while (true) {
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
//3.接收消息
new Thread(()->{
DataInputStream dis =null;
DataOutputStream dos= null;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
boolean isRunning = true;
while (isRunning) {
String msg = null;
try {
msg = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
//4.返回消息
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
//e.printStackTrace();
isRunning = false;//停止线程
}
//释放资源
}
try {
if (null==dos){
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null==dis){
dis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null==client){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
最终版
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.Channel;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 在线聊天室 :服务器
* 目标:私聊
*/
public class Chat {
private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<Channel>();
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
//1.指定端口 使用ServerSocket创建服务器
ServerSocket server = new ServerSocket(8888);
//2.阻塞式等待连接 accept
while (true) {
Socket client = server.accept();
System.out.println("一个客户端进行了连接");
Channel c = new Channel(client);
all.add(c); //管理所有的成员
new Thread(c).start();
}
}
//一个客户代表一个Channel
static class Channel implements Runnable {
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Channel(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
isRunning = true;
//获取名称
this.name= recieve();
//欢迎你的到来
this.send("欢迎你的到来");
sendOthers(this.name+"来到了太理1号楼308宿舍聊天室",true);
} catch (IOException e) {
System.out.println("-----1-----");
release();
}
}
//接收消息
private String recieve() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
System.out.println("-----2-----");
release();
}
return msg;
}
//发送消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("-----3-----");
release();
}
}
/**
* 群聊:获取自己的消息 发给其他人
* 私聊:约定数据格式
*/
private void sendOthers(String msg,boolean isSys) {
boolean isPrivate = msg.startsWith("@");
if (isPrivate) { //私聊
int idx = msg.indexOf(":");
//获取目标和数据
String targetName = msg.substring(1, idx);
msg = msg.substring(idx+1);
for (Channel other : all) {
if (other.name.equals(targetName)) { //目标
other.send(this.name + "悄悄地对您说:" + msg);
break;
}
}
} else {
for (Channel other : all) {
if (other == this) { //自己
continue;
}
if (!isSys) {
other.send(this.name + "对所有人说:" + msg);//群聊消息
} else {
other.send(msg); //系统消息
}
}
}
}
//释放资源
private void release() {
this.isRunning = false;
SxtUtils.close(dis,dos,client);
//退出
all.remove(this);
sendOthers(this.name + "离开大家庭...", true);
}
@Override
public void run() {
while (isRunning) {
String msg = recieve();
if (!msg.equals("")) {
//send (msg)
sendOthers(msg, false);
}
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 在线聊天室 :客户端
* 目标 :私聊
*/
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("-----Client-----");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name = br.readLine();
//1.建立连接:使用Socket创建客户端+服务的地址和端口
Socket client = new Socket("localhost",8888);
//2.客户端发送消息
new Thread(new Send(client,name)).start();
new Thread(new Recieve(client)).start();
}
}
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 使用多线程封装:接收端
* 1.接收消息
* 2.释放资源
* 3.重写run
*/
public class Recieve implements Runnable{
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Recieve(Socket client){
this.client = client;
this.isRunning = true;
try {
dis = new DataInputStream(client.getInputStream());
}catch (IOException e){
System.out.println("=====2=====");
release();
}
}
//接受消息
private String recieve(){
String msg = "";
try {
msg = dis.readUTF();
}catch (IOException e){
System.out.println("=====4=====");
release();
}
return msg;
}
@Override
public void run() {
while (isRunning){
String msg = recieve();
if (!msg.equals("")){
System.out.println(msg);
}
}
}
//释放资源
private void release(){
this.isRunning = false;
SxtUtils.close(dis,client);
}
}
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 使用多线程封装:发送端
* 1.发送消息
* 2.从控制台获取消息
* 3.释放资源
* 4.重写run
*
*/
public class Send implements Runnable{
private BufferedReader console;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Send(Socket client,String name){
this.client = client;
console = new BufferedReader(new InputStreamReader(System.in));
this.isRunning = true;
this.name = name;
try {
dos = new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
}catch (IOException e){
System.out.println("===1===");
this.release();
}
}
@Override
public void run() {
while (isRunning){
String msg = getStrFromConsole();
if (!msg.equals("")){
send(msg);
}
}
}
//发送消息
private void send(String msg){
try {
dos.writeUTF(msg);
dos.flush();
}catch (IOException e){
System.out.println(e);
System.out.println("===3===");
release();
}
}
/**
* 从控制台获取消息
*/
private String getStrFromConsole(){
try {
return console.readLine();
}catch (IOException e){
e.printStackTrace();
}
return "";
}
//释放资源
private void release(){
this.isRunning = false;
SxtUtils.close(dos,client);
}
}
import java.io.Closeable;
/**
* 工具类
*/
public class SxtUtils {
/**
* 释放资源
*/
public static void close(Closeable... targets) {
for (Closeable target:targets){
try {
if(null!=target){
target.close();
}
}catch (Exception e){
}
}
}
}
上一篇: 深刻理解java中new一个对象的执行过程及类的加载顺序
下一篇: Java:网络编程 学习笔记