Socket网络编程聊天,加多线程

来源:互联网 发布:smtp 修改端口号 编辑:程序博客网 时间:2024/06/10 04:21

------------------------------------------服务端

 

package org.demo.net.socket;

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 {
 // 容器
 private List<Channel> allSockets = new ArrayList<Channel>();

 public static void main(String[] args) throws IOException {

  new Server().start();
 }

 public void start() throws IOException {
  ServerSocket server = new ServerSocket(8888);
  while (true) {
   Socket socket = server.accept();
   Channel channel = new Channel(socket);
   allSockets.add(channel);// 将管道添加到容器中去
   new Thread(channel).start();// 一条道路
  }
 }

 // 一个客服端一条道路
 class Channel implements Runnable {

  private DataOutputStream dos;
  private DataInputStream dis;
  private boolean isRunning = true;
  private String name;

  public Channel() {

  }

  public Channel(Socket socket) {
   try {
    dos = new DataOutputStream(socket.getOutputStream());
    dis = new DataInputStream(socket.getInputStream());
    // 客户端发过来服务器就读取name
    this.name = dis.readUTF();
    // 发送给自己的信息
    this.send("欢迎您进入聊天室!");
    // 发送给他人的信息
    sendOthers(this.name + "已进入聊天室!",true);
   } catch (IOException e) {
    isRunning = false;
    CloseUtil.closeAll(dos, dis);

   }
  }

  public void send(String msg) {
   if (null == msg && "".equals(msg))
    return;
   try {
    dos.writeUTF(msg);
    dos.flush();
   } catch (IOException e) {
    isRunning = false;
    CloseUtil.closeAll(dos);
    allSockets.remove(this);// 移除自身
   }

  }

  public String receive() {
   String msg = "";
   try {
    msg = dis.readUTF();
   } catch (IOException e) {
    isRunning = false;
    CloseUtil.closeAll(dis);
    allSockets.remove(this);// 移除自身
   }

   return msg;
  }

  // 发送给其他客服端
  private void sendOthers(String msg,boolean isSys) {
   
   // 约定如@Test:就是对Test进行私聊,或者就是对所有人聊天
   // 是否为私聊
   if (msg.startsWith("@") && msg.indexOf(":") > -1) {
    //获取名称与内容
    String name=msg.substring(1,msg.indexOf(":"));
    System.out.println(name+"=name");
    String context=msg.substring(msg.indexOf(":")+1);
    for (Channel other : allSockets) {
     if(other.name.equals(name))
      other.send(this.name+"悄悄地对您说:"+context);
    }
    
   } else {
    // 群聊
    for (Channel other : allSockets) {
     // 如果发送等于自己就不用发送给自己了
     if (other == this)
      continue;
     
     if(isSys)
      other.send("系统消息:"+msg);
     else 
     // 否者就发给其他客服端
     other.send(this.name+"对所有人说:"+msg);
    }
   }

  }

  public void run() {
   while (isRunning) {
    sendOthers(receive(),false);
   }
  }

 }
}

 

---------------------------------------------------客服端

package org.demo.net.socket;

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

public class Client {
 public static void main(String[] args) throws UnknownHostException,
   IOException {

  Socket socket = new Socket("127.0.0.1", 8888);
  // 从控制台输入姓名
  System.out.println("您好,请输入您的名称:");
  BufferedReader conlse = new BufferedReader(new InputStreamReader(
    System.in));
  // 获取到从控制台输入的信息
  String name = conlse.readLine();
  if (null == name && "".equals(name))
   return;

  new Thread(new Send(socket, name)).start();
  new Thread(new Receive(socket)).start();

 }
}

 

--------------------------------------发送

package org.demo.net.socket;

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 {
 private BufferedReader reader;
 private DataOutputStream dos;
 //姓名
 private String name;
 // 线程标记
 private boolean isRunnable = true;

 // 从控制台接受信息
 public Send() {
  reader = new BufferedReader(new InputStreamReader(System.in));
 }

 public Send(Socket socket,String name) {
  this();
  try {
   dos = new DataOutputStream(socket.getOutputStream());
   this.name=name;
   //发送给自己,如XXX已进入聊天室
   this.send(name);
  } catch (IOException e) {
   // 链接异常
   isRunnable = false;
   // 关闭流
   CloseUtil.closeAll(dos, reader);
  }
 }

 public String getMessage() {
  try {
   return reader.readLine();
  } catch (IOException e) {
   isRunnable = false;
   CloseUtil.closeAll(reader, dos);
  }
  return "";
 }

 // 发送消息
 public void send(String msg) {
  if (null != msg && !"".equals(msg)) {
   try {
    dos.writeUTF(msg);
    dos.flush();
   } catch (IOException e) {
    isRunnable = false;
    CloseUtil.closeAll(reader, dos);
   }
  }

 }

 // 线程体
 public void run() {
  while(isRunnable)
   send(getMessage());
 }

}

 

 

-----------------------------------接受

package org.demo.net.socket;

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

//封装接受消息
public class Receive implements Runnable {

 private DataInputStream dis;
 private boolean isRunnable = true;

 public Receive() {

 }

 public Receive(Socket socket) {
  try {
   dis = new DataInputStream(socket.getInputStream());
  } catch (IOException e) {
   isRunnable = false;
   CloseUtil.closeAll(dis);
  }
 }
 //接受消息
 public String receive() {
  try {
   String msg = dis.readUTF();
   return msg;
  } catch (IOException e) {
   isRunnable = false;
   CloseUtil.closeAll(dis);
  }
  return "";
 }

 // 线程体
 public void run() {
  while (isRunnable)
   System.out.println(receive());

 }

}

 

-----------------------------------------------关闭资源

 

 

package org.demo.net.socket;

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

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

 

 

0 0