很久以前的一个Demo,这里服务器只做转发功能,根据ID地址和端口号来标识身份,群聊和私聊只是简单实现,

服务器代码如下:

import java.util.*;
import java.io.*;
import java.net.*; public class Server extends Thread
{
private static Vector<Socket> vecClient = new Vector<Socket>();
private PrintWriter out;
private BufferedReader in;
private Socket clientsocket; public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(2014); // 创建
System.out.println("启动服务器! ");
Socket sock; while (true) {
sock = server.accept(); // 等待客户请求
Server ser = new Server(sock);
ser.start(); // 启动
}
} public Server(Socket socket) {
this.clientsocket = socket;
vecClient.addElement(socket); // 增加客户线程到数组
try {
// 获取服务端传来的字节流好,存到缓冲区
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// printwriter,文本输出流打印对象的格式化表示形式,只有调用println等,自动刷新即true,强行把缓冲区的数据输出。
out = new PrintWriter(new OutputStreamWriter(
socket.getOutputStream()), true);
// input、OutputStreamWriter 是字符流通向字节流的桥梁
} catch (IOException e) {
}
} public void run()
{
try
{
Newclient(); // 向新客户发出欢迎信息,通知所有在线客户有新客户连接了
while(true) // 处理与客户的交流
{
String msg=in.readLine(); //数据读取 if(msg.equals("bye")|| msg.equals("拜拜"))//当输入拜拜或bye时候退出
{
Xiaxian();
in.close(); // 关闭输入流
clientsocket.close(); // 关闭socket
break;
}
else if(msg.indexOf("@")==0&&msg.indexOf(" ")>0){
int end=msg.indexOf(" ");
String findAddr=msg.substring(1,end);
if(vecClient.isEmpty() == false) //判断为空
{
for(int i=0;i<vecClient.size();i++)
{
Socket socket = vecClient.get(i);
String addr = socket.getInetAddress().toString().replace("/", "") + ":"
+ socket.getPort();
if(findAddr.equals(addr)){
String addr2 = clientsocket.getInetAddress().toString().replace("/", "") + ":"
+ clientsocket.getPort();
//elementAt返回指定索引处的组件,而get返回列表中指定位置处的元素
PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient.get(i).getOutputStream()),true);
pw.println("大神"+addr2+" 对你 说: "+msg.substring(end));
}
}
}
}
// 否则将接收到的信息向所有在线客户发出去
else
{
if(vecClient.isEmpty() == false)
for(int i=0;i<vecClient.size();i++)
{
//elementAt返回指定索引处的组件,而get返回列表中指定位置处的元素
PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient.get(i).getOutputStream()),true);
pw.println("大神"+clientsocket.getInetAddress().toString()+":"+clientsocket.getPort()+" 说: "+msg);
}
}
}
}
catch(IOException e)
{ }
} public void Newclient() throws IOException // 新来的,用此函数
{
String addr = clientsocket.getInetAddress().toString() + ":"
+ clientsocket.getPort();
out.println("欢迎:" + addr+"加入! ");
try {
if (vecClient.isEmpty() == false)
for (int i = 0; i < vecClient.size(); i++)
{
Socket socket = vecClient.get(i);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(
socket.getOutputStream()), true);
String addr2 = socket.getInetAddress().toString() + ":"
+ socket.getPort();
if (addr.equals(addr2)) {
pw.println("欢迎加入聊天,私聊请用@ip:port 内容");
} else {
pw.println("新成员:"
+ clientsocket.getInetAddress().toString()
+ ":" + clientsocket.getPort() + " 嗨起来吧!");
}
}
} catch (IOException e) {
}
} public void Xiaxian() throws IOException // 下线方法
{
out.println("再见,连接关闭!");
if (vecClient.isEmpty() == false)
for (int i = 0; i < vecClient.size(); i++) {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient
.get(i).getOutputStream()), true);
pw.println("--" + clientsocket.getInetAddress().toString()
+ ":" + clientsocket.getPort() + " 已经下线");
}
vecClient.remove(clientsocket);
}
}

客服端,可在本地命令运行多个测试,私聊格式:@ip:port(这里必须有空格)内容,原理如下:

import java.net.*;
import java.io.*;
import java.util.*; class Client
{
public static void main(String[] args)
{
try
{
Socket socket=new Socket("localhost",2014);
ClientSend send=new ClientSend(socket); // 创建发送线程
ClientReceive receive=new ClientReceive(socket); // 创建接收线程
send.start(); // 启动发送线程
receive.start(); // 启动接收线程
}
catch(Exception e)
{
System.out.println("服务器没有开启呢!");
e.printStackTrace();
} }
} class ClientSend extends Thread
{
private Socket socket;
private PrintWriter out; public ClientSend(Socket socket)
{
this.socket=socket;
try
{
out=new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
//返回一个服务器与客户端的输出流,true强行把缓冲区的数据输出
}
catch(IOException e)
{
e.printStackTrace();
}
} public void run() // 发送信息到服务器
{
String msg;
Scanner input=new Scanner(System.in);//输入
msg = input.nextLine(); //nextLine方法返回的是回车之前的所有字符
while(true)
{
//用equalsIgnoreCase可忽略大小写
if(msg.equals("bye") || msg.equals("拜拜"))
{
out.println(msg);
break;
}
out.println(msg);
msg = input.nextLine();
}
}
} class ClientReceive extends Thread //接收
{
private Socket socket;
private BufferedReader in; public ClientReceive(Socket socket)
{
this.socket= socket;
try
{
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch(IOException e)
{
e.printStackTrace();
}
} public void run() // 接收服务器发来的信息
{
try
{
String msg=in.readLine();
while(msg.equals("bye") == false)
{
System.out.println(msg);
msg=in.readLine();
}
in.close();
socket.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}

Socket通信 简单实现私聊、群聊(dos命令下)的更多相关文章

  1. 简单通讯聊天 群聊功能 Windows下的客户端 Linux下的epoll服务器

    1 服务器代码  Linux eclipse C++ //======================================================================= ...

  2. 基于ejabberd简单实现xmpp群聊离线消息

    首先,xmpp服务器是基于ejabberd.离线消息模块是mod_interact,原地址地址:https://github.com/adamvduke/mod_interact: 修改后实现群聊离线 ...

  3. Java在DOS命令下的运行及其API文档制作过程

    该文档主要描述java程序在DOS命令下的运行,以及一些常用的命令 常用DOS命令: d: 回车 盘符切换 dir(directory):列出当前目录下的文件以及文件夹 md (make direct ...

  4. DOS命令下输入:java Hello 出现以下几种结果可能的原因:

    DOS命令下输入:java Hello 出现以下结果:Bad command or the file name 没有这个命令或文件名 原因可能是没有成功安装jdk或者没有配置好jdk 的环境变量,或者 ...

  5. 安装Oracle之后在DOS命令下不能使用sqlplus命令启动Oracle?

    就像完成安装JDK后需要给系统配置环境变量JAVA_HOME和PATH,以便让系统认识在JDK里面的Javac命令.同样的,安装Oracle也需要这么一个过程.在正常情况下安装Oracle时系统安装程 ...

  6. Dos命令下目录操作

    Dos命令下目录操作 1.cd 操作 显示当前目录名或改变当前目录 cd [盘符][路径]                      进入指定盘符下的目录 cd [..]               ...

  7. dos命令下安装pip报错 不是内部命令

    在dos命令下: pip install requests 遇到这种情况一般是Python的环境变量没有设置好 解决方案一:设置环境变量 C:\Python\scripts   如图 是否有pytho ...

  8. 第五讲 smart qq poll包处理 以及 私聊 群聊消息收发

    发送 poll包 public static void Login_PostPoll() { try { string url = "http://d1.web2.qq.com/channe ...

  9. Java的Socket通信简单实例

    服务端 package testlxd; import java.io.BufferedReader; import java.io.IOException; import java.io.Input ...

随机推荐

  1. springmvc使用freemarker

    首先需要添加freemarker.jar到项目,如果项目中有spring或者spirngmvc,需要整合,首先配置freemarkerConfig,代码结构如下 <!-- 设置freeMarke ...

  2. Spring MVC中Action使用总结

    Spring MVC中每个控制器中可以定义多个请求处理方法即Action,Action可以有多个不同的参数,有多种类型的返回结果. 可以作为Action的参数类型有: 表单对象基本数据类型,包括包装类 ...

  3. Query Designer:Exception,不同的值显示不同的颜色

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  4. Java资源大全中文版(Awesome最新版)(转载)

    原文地址:http://www.cnblogs.com/best/p/5876559.html 目录 业务流程管理套件 字节码操作 集群管理 代码分析 编译器生成工具 构建工具 外部配置工具 约束满足 ...

  5. 界面布局之表格布局TableLayout+TableRow

    一.基础知识: TableLayout置底,TableRow在TableLayout的上面,而Button.TextView等控件就在TableRow之上, 另外,TableLayout之上也可以单独 ...

  6. DNS域名解析服务器

    域名解析服务器,靠它把你要访问的网址找到然后把信息送到你电脑上.DNS 是域名系统 (Domain Name System) 的缩写,它是由解析器和域名服务器组成的.域名服务器是指保存有该网络中所有主 ...

  7. java中myeclipse连接mysql问题(java.lang.ClassNotFoundException: com.mysql.jdbc.Driver)

    java中myeclipse连接mysql问题(java.lang.ClassNotFoundException: com.mysql.jdbc.Driver) 1.往项目中添加mysql-conne ...

  8. position absolute 绝对定位 设置问题

     今天在做布局的时候,用到了绝对定位, 父级元素相对定位,子元素两个,一个元素正常文档流布局并且在前面,另一个元素绝对定位排在后面,但设置了好久,绝对定位的子元素都不会覆盖其上面的兄弟元素,最后,不知 ...

  9. web前端学习(二) javascript对象和原型继承

    目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...

  10. ubuntu16.04 + ubuntu + apache2 配置apache解析php

    给apache安装php扩展:  sudo apt-get install libapache2-mod-php 注:这是apache解析php文件的关键,光修改配置文件不安装扩展是不起作用的. 目录 ...