Socket通信 简单实现私聊、群聊(dos命令下)

很久以前的一个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();
        }
    }
}

时间: 2024-12-15 20:15:39

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

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

1 服务器代码  Linux eclipse C++ 1 //============================================================================ 2 // Name : epollServer.cpp 3 // Author : fangjunmin 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C

dos命令下使用sql server

通常情况下,我们可以在dos命令下使用sql server,使用dos命令来使用sql server的方法如下: 1.连接上数据库服务器: 使用osql命令,该命令可以在dos窗口中输入osql ?查看,如: 接下来我们使用osql  -S localhost -U sa -P 123456连接上我们的数据库服务器. 2.而后使用sql语句查询数据库中所有数据库名: 3.我们可以使用sql语句获取某个数据库下的所有的表的名称 其他的操作不再多述.

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

就像完成安装JDK后需要给系统配置环境变量JAVA_HOME和PATH,以便让系统认识在JDK里面的Javac命令.同样的,安装Oracle也需要这么一个过程.在正常情况下安装Oracle时系统安装程序会自动配置环境变量,但如果安装过程中配置环境变量时发生错误,或者在安装成功后将系统给Oracle配置的环境变量删除,就会导致在DOS命令下系统不认识sqlplus命令,不能使用. 解决方法:先找到自己Oracle的安装目录 D:\app\Administrator\product\11.2.0\d

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

DOS命令下输入:java Hello 出现以下结果:Bad command or the file name 没有这个命令或文件名 原因可能是没有成功安装jdk或者没有配置好jdk 的环境变量,或者没有编译相应的文件. 2. 出现以下结果:Exception in thread “main” java.lang.NoClassDefFoundError: Hello 可能是什么原因 可能是没有定义类,直接写进main的字节码中. 记住,javac后面跟的参数是文件名,但java 后面跟的是类名

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

该文档主要描述java程序在DOS命令下的运行,以及一些常用的命令 常用DOS命令: d: 回车 盘符切换 dir(directory):列出当前目录下的文件以及文件夹 md (make directory) : 创建目录 rd (remove directory): 删除目录 cd (change directory)改变指定目录(进入指定目录) cd.. : 退回到上一级目录 cd\: 退回到根目录 del (delete): 删除文件,删除一堆后缀名一样的文件*.txt exit : 退出

Java环境配置及在Dos命令下运行Java程序

Java环境配置及在Dos命令下运行Java程序 1. JDK下载 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html 点击DOWNLOAD 首先点击安装许可协议 然后点击相应的版本下载,如果是windows点击如下: 安装成功以后 打开命令提示符,输入:java,出现如下提示表示安装成功! 2. Java环境配置 找到我的电脑->(鼠标右击)属性->高级系统设置->高级->环境变量-&g

C# Socket通信简单实例

一.套接字(socket)概念 套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口. 应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算机操作系统为应用

DOS命令下的一些操作

  DOS和Windows最大的不同在于DOS命令方式操作,所以使用者需要记住大量命令及其格式使用方法,DOS命令分为内部命令和外部命令, 内部 命令是随每次启动的COMMAND.COM装入并常驻内存,而外部命令是一条单独的可执行文件.在操作时要记住的是,内部命令在任何时候都可以使 用,而外部命令需要保证命令文件在当前的目录中,或在Autoexec.bat文件已经被加载了路径. e: 进入e盘 dir(directory):目录 查看当前文件夹下的所有目录 cd(change directory

socket通信简单介绍

“一切皆Socket!” 话虽些许夸张,可是事实也是,如今的网络编程差点儿都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间怎样通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与webserver通信的?当你用QQ聊天时,QQ进程怎么与server或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的.本文的主要内容例如以下: 1.网络中进程之间怎