BS和CS
网络编程三要素
IP
IPv6还不够普及,那么目前如何解决ip地址不够用的问题呢
端口号
协议
UDP通信程序
发送数据
package com.company.net;
import java.io.IOException;
import java.net.*;
public class UDPsendMessage {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象
/**
* 绑定端口,以后我们就通过这个端口往外发送数据
* 空参:所有可用的端口中随机一个进行使用
* 有参:指定端口号进行绑定
*/
DatagramSocket ds = new DatagramSocket();
//2.打包数据
String str = "你好啊";
byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//3.发送数据
ds.send(dp);
//4.释放资源
ds.close();
}
}
接收数据
package com.company.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceiveMessage {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象
/**
* 接收的时候一定要绑定端口
* 绑定的端口和发送的一致
*/
DatagramSocket ds = new DatagramSocket(10086);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
//该方法是阻塞的,等待发送端发送消息
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
InetAddress address = dp.getAddress();
int port = dp.getPort();
System.out.println("接收到的数据"+new String(data,0,len));
System.out.println("该数据是从"+address+"这台电脑的"+port+"端口发送的");
//4.释放资源
ds.close();
}
}
先运行接收数据代码、在运行发送数据代码
聊天室
将发送端运行多次,模拟聊天室,都发送消息 ,
UDP三种通信方式
创建多个接收端:
TCP通信程序
综合练习
1.多发多收
客户端:
package com.company.net;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class TestOneClient {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务端
Socket socket = new Socket("127.0.0.1",10000);
//2.写出数据
Scanner sc = new Scanner(System.in);
OutputStream os = socket.getOutputStream();
while (true) {
System.out.println("请输入您想发送的信息");
String str = sc.nextLine();
if (str.equals("886")){
break;
}
os.write(str.getBytes());
}
//3.释放资源
socket.close();
}
}
服务端:
package com.company.net;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TestOneServer {
public static void main(String[] args) throws IOException {
//1.创建对象绑定10000端口
ServerSocket ss = new ServerSocket(10000);
//2.等待客户端来连接
Socket socket = ss.accept();
//3.读取数据
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
int b;
while ((b = isr.read()) != -1){
System.out.print((char)b);
}
//4.释放资源
socket.close();
ss.close();
}
}
2.接收并反馈
客户端:
package com.company.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class TestTwoCilent {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务端
Socket socket = new Socket("127.0.0.1",10000);
//2.写出数据
String str = "见到你很高兴";
OutputStream os = socket.getOutputStream();
os.write(str.getBytes());
//结束输出标志,没有这个,server就会一直在while里面,不会进行回写
socket.shutdownOutput();
//接收server发的消息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int b;
while ((b = isr.read()) != -1){
System.out.println((char)b);
}
socket.close();
}
}
服务端:
package com.company.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TestTwoServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10000);
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int b;
while ((b = isr.read()) != -1){
System.out.print((char)b);
}
//回写数据
String str = "到底有多开心啊?";
OutputStream os = socket.getOutputStream();
os.write(str.getBytes());
socket.close();
ss.close();
}
}
3.上传文件
服务端:
package com.company.net;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Test3Server {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss = new ServerSocket(10000);
//2.等待客户端来连接
Socket socket = ss.accept();
//3.读取数据并把保存到本地文件中
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\com\\company\\net\\serverdir\\a.jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//回写数据
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream())));
bw.write("上传成功");
bw.newLine();
bw.flush();
socket.close();
ss.close();
}
}
客户端:
package com.company.net;
import java.io.*;
import java.net.Socket;
public class Test3Client {
public static void main(String[] args) throws IOException {
//1.创建Socket对象,并连接服务器
Socket socket = new Socket("127.0.0.1",10000);
//2.读取本地文件中的数据,并写到服务器当中
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src\\com\\company\\net\\clientdir\\000001.jpeg"));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//往服务器写出结束标记
socket.shutdownOutput();
//接收服务器的回写数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = br.readLine();
System.out.println(s);
socket.close();
}
}
4.文件名重复问题
package com.company.net;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Test3Server {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss = new ServerSocket(10000);
//2.等待客户端来连接
Socket socket = ss.accept();
//3.读取数据并把保存到本地文件中
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\com\\company\\net\\serverdir\\"+name+".jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//回写数据
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream())));
bw.write("上传成功");
bw.newLine();
bw.flush();
socket.close();
ss.close();
}
}
5.上传文件(多线程版)
服务端:
package com.company.net;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Test3Server {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss = new ServerSocket(10000);
while (true) {
//2.等待客户端来连接
//开启一条线程
//一个用户就对应服务端的一条线程
Socket socket = ss.accept();
new Thread(new MyRunnable(socket)).start();
}
}
}
线程:
package com.company.net;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunnable implements Runnable{
Socket socket;
public MyRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//3.读取数据并把保存到本地文件中
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\com\\company\\net\\serverdir\\"+name+".jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//回写数据
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(socket.getOutputStream())));
bw.write("上传成功");
bw.newLine();
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6.上传文件(线程池优化)
package com.company.net;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test3Server {
public static void main(String[] args) throws IOException {
//创建线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,//核心线程数量
16,//线程池总大小
60,//空闲时间
TimeUnit.SECONDS,//空闲时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂,让线程池如何创建线程对象
new ThreadPoolExecutor.AbortPolicy()//任务拒绝策略
);
//1.创建对象并绑定端口
ServerSocket ss = new ServerSocket(10000);
while (true) {
//2.等待客户端来连接
//开启一条线程
//一个用户就对应服务端的一条线程
Socket socket = ss.accept();
// new Thread(new MyRunnable(socket)).start();
pool.submit(new MyRunnable(socket));
}
}
}
7.接收浏览器消息并打印
8.控制台版聊天室
项目名称
利用TCP协议,做一个带有登录,注册的无界面,控制台版的多人聊天室。
使用到的知识点
循环,判断,集合,IO,多线程,网络编程等
准备工作
在当前模块下新建txt文件,文件中保存正确的用户名和密码
文件内容如下:
//左边是用户名
//右边是密码
zhangsan=123
lisi=1234
wangwu=12345
需求描述
① 客户端启动之后,需要连接服务端,并出现以下提示:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
②选择登录之后,出现以下提示:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
1
请输入用户名
③需要输入用户名和密码,输入完毕,没有按回车时,效果如下:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
1
请输入用户名
zhangsan
请输入密码
123
④按下回车,提交给服务器验证
服务器会结合txt文件中的用户名和密码进行判断
根据不同情况,服务器回写三种判断提示:
服务器回写第一种提示:登录成功
服务器回写第二种提示:密码有误
服务器回写第三种提示:用户名不存在
⑤客户端接收服务端回写的数据,根据三种情况进行不同的处理方案
登录成功的情况, 可以开始聊天,出现以下提示:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
1
请输入用户名
zhangsan
请输入密码
123
1
登录成功,开始聊天
请输入您要说的话
密码错误的情况,需要重新输入,出现以下提示:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
1
请输入用户名
zhangsan
请输入密码
aaa
密码输入错误
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
用户名不存在的情况,需要重新输入,出现以下提示:
服务器已经连接成功
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
1
请输入用户名
zhaoliu
请输入密码
123456
用户名不存在
==============欢迎来到黑马聊天室================
1登录
2注册
请输入您的选择:
⑥如果成功登录,就可以开始聊天,此时的聊天是群聊,一个人发消息给服务端,服务端接收到之后需要群发给所有人
提示:
此时不能用广播地址,因为广播是UDP独有的
服务端可以将所有用户的Socket对象存储到一个集合中
当需要群发消息时,可以遍历集合发给所有的用户
此时的服务端,相当于做了一个消息的转发
转发核心思想如下图所示:
其他要求:
用户名和密码要求:
要求1:用户名要唯一,长度:6~18位,纯字母,不能有数字或其他符号。
要求2:密码长度3~8位。第一位必须是小写或者大写的字母,后面必须是纯数字。
客户端:
拥有登录、注册、聊天功能。
① 当客户端启动之后,要求让用户选择是登录操作还是注册操作,需要循环。
如果是登录操作,就输入用户名和密码,以下面的格式发送给服务端
username=zhangsan&password=123
如果是注册操作,就输入用户名和密码,以下面的格式发送给服务端
username=zhangsan&password=123
② 登录成功之后,直接开始聊天。
服务端:
① 先读取本地文件中所有的正确用户信息。
② 当有客户端来链接的时候,就开启一条线程。
③ 在线程里面判断当前用户是登录操作还是注册操作。
④ 登录,校验用户名和密码是否正确
⑤ 注册,校验用户名是否唯一,校验用户名和密码的格式是否正确
⑥ 如果登录成功,开始聊天
⑦ 如果注册成功,将用户信息写到本地,开始聊天
客户端:
package com.company.net.chatRoom.Client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientRunnable implements Runnable {
//创建Socket对象,用于接收当前客户端的连接对象
Socket socket;
//有参构造方法:用于创建一个单独线程来专门接收服务端转发过来的聊天记录
public ClientRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = br.readLine();
System.out.println(msg);
} catch (IOException e) {
System.out.println("群聊已解散");
// e.printStackTrace();
System.exit(0);
}
}
}
package com.company.net.chatRoom.Client;
import java.io.*;
import java.net.Socket;
import java.util.Properties;
import java.util.Scanner;
public class Client {
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) throws IOException {
//连接服务器
Socket socket = new Socket("127.0.0.1",10000);
System.out.println("服务器已经连接成功");
//主界面
while(true){
System.out.println("==============欢迎来到奥利给聊天室================");
System.out.println("1.登录");
System.out.println("2.注册");
System.out.println("请输入您的选择:");
String choose = sc.nextLine();
switch (choose){
case "1":
//登录
login(socket);
break;
case "2":
//注册
register(socket);
break;
case "3":
System.out.println("目前还没此选项~请重试");
break;
}
}
}
//用户注册
private static void register(Socket socket) throws IOException {
//获取输出流:用于向服务端写出数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读取本地文件中所有正确用户信息(用户名和密码)
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("E:\\Defect_Detection\\Code\\JAVA\\my\\src\\com\\company\\net\\chatRoom\\ServerDir\\userInfro");
prop.load(fis);
fis.close();
//键盘录入用户名和密码
System.out.println("请输入注册的用户名:");
String username = sc.nextLine();
//要求1.用户名唯一
if(prop.containsKey(username)){
System.out.println("用户名已存在!");
return;
}
// 长度:6~18位,纯字母,不能有数字或其他符号。
if (!username.matches("[a-zA-Z]{6,18}")) {
System.out.println("注册的用户名不符合要求(长度6~18位、纯字母、不能有数字或其他符号)");
return;
}
System.out.println("请输入注册的密码:");
String password = sc.nextLine();
System.out.println("请再次确认注册密码:");
String okPassword = sc.nextLine();
// 要求2:密码长度3~8位。第一位必须是小写或者大写的字母,后面必须是纯数字。
String passwordRegex = "[a-zA-Z]{1}[0-9]{2,7}";
if (!(password.matches(passwordRegex) || okPassword.matches(passwordRegex))){
System.out.println("注册的密码不符合要求(长度3~8位,第一位必须是小写或者大写的字母,后面必须是纯数字)");
return;
}
//判断两次密码不一致
if (!password.equals(okPassword)) {
System.out.println("您输入的两次密码不一致!!");
return;
}
//拼接用户名和密码的格式为:username=password
StringBuilder sb = new StringBuilder();
sb.append("username=").append(username).append("&password=").append(password);
//第一次写的是执行注册操作
bw.write("register");
bw.newLine(); //换行
bw.flush(); //刷新
//第二次写的是用户名、密码的信息
//往服务端写出用户名和密码
bw.write(sb.toString());
bw.newLine();
bw.flush();
//接收服务端回写的数据
//获取输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = br.readLine();
System.out.println("服务端回馈数据:" + message);
// 1: 注册成功
if (message.equals("1")) {
System.out.println("注册成功~");
//开启一条单独的线程,专门用来接收服务端发送过来的聊天记录
new Thread(new ClientRunnable(socket)).start();
//开始聊天:就是把消息写到服务端,然后服务端会将当前客户端的消息群发给所有在线的客户端
talkServer(bw);
}
}
//用户登录
private static void login(Socket socket) throws IOException {
//获取输出流:用于向服务端写出数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//键盘录入用户名和密码
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
//拼接用户名和密码
StringBuilder sb = new StringBuilder();
sb.append("username=").append(username).append("&password=").append(password);
//第一次写的是执行登录操作
bw.write("login");
bw.newLine();//换行
bw.flush();
//第二次写的是用户名、密码的信息
//往服务端写出用户名和密码
bw.write(sb.toString());
bw.newLine();
bw.flush();
//接收服务端回写的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = br.readLine();
System.out.println("服务器回馈数据:"+message);
// 1: 登录成功;2: 密码有误;3: 用户名不存在
if (message.equals("1")){
System.out.println("登陆成功");
//开启一条单独的线程,专门用来接收服务端发送过来的聊天记录
new Thread(new ClientRunnable(socket)).start();
//开始聊天:就是把消息写到服务端,然后服务端会将当前客户端的消息群发给所有在线的客户端
talkServer(bw);
}else if (message.equals("2")){
System.out.println("密码有误!!");
}else if (message.equals("3")){
System.out.println("用户名不存在");
}
}
private static void talkServer(BufferedWriter bw) throws IOException {
System.out.println("请输入您想说的话:");
String message = sc.nextLine();
//把输入的话写给服务端
bw.write(message);
bw.newLine();
bw.flush();
}
}
服务端:
package com.company.net.chatRoom.Server;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Properties;
public class Server {
//定义集合用于存储每一个客户端的连接对象
public static ArrayList<Socket> socketList = new ArrayList<>();
public static void main(String[] args) throws IOException {
//创建ServerSocket对象,并绑定端口号
ServerSocket ss = new ServerSocket(10000);
//先读取本地文件中所有的正确用户信息(用户名和密码)
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("E:\\Defect_Detection\\Code\\JAVA\\my\\src\\com\\company\\net\\chatRoom\\ServerDir\\userInfro");
prop.load(fis);
fis.close();
//当有客户端来连接的时候,就开启一条线程
while (true) {
Socket socket = ss.accept();
System.out.println("有客户端来连接了~");
new Thread(new ServerRunnable(socket, prop)).start();
}
}
}
package com.company.net.chatRoom.Server;
import java.io.*;
import java.net.Socket;
import java.util.Properties;
public class ServerRunnable implements Runnable{
//创建Socket、Properties对象
//socket: 用于接收每一个客户端的socket连接对象
//prop: 用于接收所有的正确用户信息
public static Properties prop;
Socket socket;
//线程类的有参构造方法:当有客户端来连接时,开启一条线程
//并将该客户端的socket连接对象 和 所有的正确用户信息初始化给当前线程对象的socket、prop
public ServerRunnable(Socket socket,Properties prop) {
this.prop = prop;
this.socket = socket;
}
@Override
public void run() {
try {
//获取输入流:用于读取客户端的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取用户名的选项
while (true) {
String choose = br.readLine();
//判断当前用户是选择了登录操作还是注册操作
switch (choose) {
case "login": //用户选择了登录
login(br);
break;
case "register": //用户选择了注册
register(br);
break;
}
}
} catch (IOException e) {
// throw new RuntimeException(e);
System.out.println("有客户端下线了~");
}
}
private void register(BufferedReader br) throws IOException {
System.out.println("用户选择了注册~");
//读取该用户输入的用户名和密码信息:username=xxx&password=xxx
String userInfo = br.readLine();
//根据 "&" 将用户名和密码进行分裂
//分裂后得到一个字符串数组:
// 0索引就是:username=xxx
// 1索引就是:password=xxx
String[] userInfoArr = userInfo.split("&");
// 得到用户输入的用户名
String usernameInput = userInfoArr[0].split("=")[1];
System.out.println("用户输入的用户名为:" + usernameInput);
// 得到用户输入的密码
String passwordInput = userInfoArr[1].split("=")[1];
System.out.println("用户输入的密码为:" + passwordInput);
//拼接用户信息的格式为:username=password
StringBuilder sb = new StringBuilder();
sb.append(usernameInput).append("=").append(passwordInput);
//将新注册的用户名和密码写入userInfo.txt文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\Defect_Detection\\Code\\JAVA\\my\\src\\com\\company\\net\\chatRoom\\ServerDir\\userInfro", true));
bw.write(sb.toString());
bw.newLine();
bw.flush();
//新用户注册成功,回写一个1给客户端
writerMessageClient("1");
//把当前注册成功的客户端的socket连接对象存储到socketList集合中
Server.socketList.add(socket);
//接收客户端发过来的消息,群发给每一个客户端
talkAllClient(br, usernameInput);
}
private void login(BufferedReader br) throws IOException {
System.out.println("用户选择了登录~");
//读取该用户输入的用户名和密码信息:username=xxx&password=xxx
String userInfo = br.readLine();
//根据 "&" 将用户名和密码进行分裂
//分裂后得到一个字符串数组:
// 0索引就是:username=xxx
// 1索引就是:password=xxx
String[] userInfoArr = userInfo.split("&");
//再根据 "=" 将0索引的用户名
//分裂后得到一个字符串数组
// 0索引就是:username
// 1索引就是:xxx
String[] usernameArr = userInfoArr[0].split("=");
// 得到用户输入的用户名
String usernameInput = usernameArr[1];
System.out.println("用户输入的用户名为:" + usernameInput);
//再根据 "=" 将1索引的密码
//分裂后得到一个字符串数组
// 0索引就是:password
// 1索引就是:xxx
String[] passwordArr = userInfoArr[1].split("=");
// 得到用户输入的密码
String passwordInput = passwordArr[1];
System.out.println("用户输入的密码为:" + passwordInput);
//校验用户名是否正确(其实就是判断用户名是否存在)
if (prop.containsKey(usernameInput)) {
//用户名存在,则校验密码是否正确
// 根据用户名获取对应的密码,并转换成字符串类型(方便比较)
String rightPassword = prop.get(usernameInput) + "";
if (rightPassword.equals(passwordInput)) {
//程序到这里,说明用户输入用户名和密码都正确了,回写一个1(登录成功)给客户端
writerMessageClient("1");
//把当前登录成功的客户端的socket连接对象存储到socketList集合中
Server.socketList.add(socket);
//接收客户端发过来的消息,群发给每一个客户端
talkAllClient(br, usernameInput);
}else {
//密码错误,回写一个2给客户端
writerMessageClient("2");
}
}else {
//用户名不存在,回写一个3给客户端
writerMessageClient("3");
}
}
private void talkAllClient(BufferedReader br, String username) throws IOException {
while (true) {
String message = br.readLine();
System.out.println(username + "说:" + message);
//将当前客户端发送过来的消息群发给所有在线的客户端
for (Socket s : Server.socketList) {
//s表示每一个客户端的连接对象
writerMessageClient(s, username + "说:" + message);
}
}
}
//回写数据给客户端
public void writerMessageClient(String message) throws IOException {
//获取输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(message);
bw.newLine();//换行
bw.flush();//刷新
}
//回写数据给客户端
public void writerMessageClient(Socket socket, String message) throws IOException {
//获取输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write(message);
bw.newLine();//换行
bw.flush();//刷新
}
}
运行效果
先运行server,再运行client,按照命令走就行了