先写一个客户端输入数据,服务器端处理数据后返回给客户端
客户端:
public static void main(String[] args) throws UnknownHostException, IOException {
Scanner sc = new Scanner(System.in);
System.out.println("请客户端输入:");
String msg = sc.nextLine();
//创建客户端 指定服务器及端口 此时就在连接
Socket client = new Socket("localhost",9999);
//客户端输出数据 输出流
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF(msg);
dos.flush();
//客户端读取数据, 输入流
DataInputStream dis = new DataInputStream(client.getInputStream());
msg = dis.readUTF();
System.out.println(msg);
}
服务器端:
public static void main(String[] args) throws IOException {
//创建服务器,指定端口
ServerSocket server = new ServerSocket(9999);
//接收客户端连接 阻塞式 该socket和客户端的socket是同一个socket
Socket socket = server.accept();
//服务器端读取数据, 输入流
DataInputStream dis = new DataInputStream(socket.getInputStream());
String msg = dis.readUTF();
//服务器端输出数据 输出流
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(msg + " 服务器端输出");
dos.flush();
}
启动服务器端后启动客户端:
请客户端输入:
你好
你好 服务器端输出
上述代码存在的问题,处理完一条数据就结束了,要想实现一直保持通信,加入死循环。输入流和输出流在同一个线程内 应该独立处理 彼此独立 引入多线程
服务器端:
public class ThreadServer {
public static void main(String[] args) throws IOException {
//创建服务器,指定端口
ServerSocket server = new ServerSocket(9999);
//接收客户端连接 阻塞式 该socket和客户端的socket是同一个socket
Socket socket = server.accept();
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while(true){
//服务器端读取数据, 输入流
String msg = dis.readUTF();
//服务器端输出数据 输出流
dos.writeUTF(msg + " 服务器端输出");
dos.flush();
}
}
}
客户端:
public class ThreadClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端 指定服务器及端口 此时就在连接
Socket client = new Socket("localhost",9999);
new Thread(new Send(client)).start(); //一条路径
new Thread(new Receive(client)).start();//另一条路径
}
}
发送数据封装类:
public class Send implements Runnable{
//输入数据 控制台
private BufferedReader console;
//输出流
private DataOutputStream dos;
//是否running
private boolean isRunning = true;
public Send(Socket client){
console = new BufferedReader(new InputStreamReader(System.in));
try {
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(console,dos);
}
}
//控制台接收数据
public String getMsgFromClient(){
try {
return console.readLine();
} catch (IOException e) {
}
return "";
}
//发送信息
public void send(){
String msg = getMsgFromClient();
try {
if(null != msg && !msg.equals("")){
dos.writeUTF(msg);
dos.flush();
}
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(console,dos);
}
}
@Override
public void run() {
while(isRunning){
send();
}
}
}
接收数据封装类:
public class Receive implements Runnable{
//输入流 读取数据
private DataInputStream dis;
//是否running
private boolean isRunning = true;
public Receive(Socket client){
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
}
}
//接收信息
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}
@Override
public void run() {
while(isRunning){
System.out.println(receive());
}
}
}
关闭流工具类:
public class CloseUtil {
public static void closeAll(Closeable... io){
for(Closeable temp : io){
try {
if(null != temp){
temp.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上述代码中只实现了一个客户端,自己发送的数据自己接收,想当与自己给自己发送数据
群发:
给所有客户端发送数据
在上述代码的基础上只需要修改服务器端的代码
public class ThreadServer {
private List list = new ArrayList();
public static void main(String[] args) throws IOException {
new ThreadServer().start();
}
public void start() throws IOException{
//创建服务器,指定端口
ServerSocket server = new ServerSocket(9999);
//接收客户端连接 阻塞式 该socket和客户端的socket是同一个socket
while(true){
Socket client = server.accept();
MyChannel channel = new MyChannel(client);
list.add(channel);
new Thread(channel).start();
}
}
/**
* 一个客户端 一条道路
*/
private class MyChannel implements Runnable{
private DataInputStream dis = null;
private DataOutputStream dos = null;
private boolean isRunning = true;
public MyChannel(Socket client){
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis,dos);
list.remove(this);
}
}
/**
* 获取数据
* @return
*/
private String receive(){
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
list.remove(this);
}
return msg;
}
/**
* 发送数据
* @param msg
*/
private void send(String msg){
try {
if(null == msg || msg.equals("")){
return;
}
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dos);
list.remove(this);
}
}
/**
* 发送给其他客户端
*/
private void sendOthers(){
String msg = this.receive();
for(MyChannel other : list){
if(other == this){
continue;
}
//发送给其他客户端
other.send(msg);
}
}
@Override
public void run() {
while(isRunning){
sendOthers();
}
}
}
}
启动服务器端 然后启动多个客户端(多次run as ThreadClient)发现,后面启动的客户端,发送的数据前面启动的客户端都会接收到
此处我启动了三个客户端
第一次启动的客户端
第二次启动
第三次启动
回头看第一次启动的界面 发现接受到了第二次和第三次的数据
回头看第二次启动的界面 发现接受到第三次的数据
自学笔记,多有不足!!!