网络编程_TCP_Socket通信_聊天室_客户端多线程_群聊JAVA191-192

来源:http://www.bjsxt.com/
一、S02E191_01网络编程TCP_Socket通信聊天室_客户端多线程
二、S02E192_01网络编程TCP_Socket通信聊天室_群聊

package com.test.net.tcp.chat;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * 创建客户端:发送数据+接收数据
 * 写出数据:输出流
 * 读取数据:输入流
 * 
 * 输入流与输出流应该独立处理,彼此独立,在不同的线程中
 */
public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket client = new Socket("LWT-PC",9999);
        //控制台输入流
        new Thread(new Send(client)).start();//一条路径
        new Thread(new Receive(client)).start();//一条路径
    }
}
package com.test.net.tcp.chat;

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<MyChannel> all = new ArrayList<MyChannel>();

    public static void main(String[] args) throws IOException {
        new Server().start();
    }

    public void start() throws IOException{
        ServerSocket server = new ServerSocket(9999);
        while(true){
            Socket client = server.accept();
            MyChannel channel = new MyChannel(client);
            all.add(channel);//统一管理
            new Thread(channel).start();//一条道路
        }
    }
    /**
     * 一个客户端一条道路
     * 1、输入流
     * 2、输出流
     * 3、接收数据
     * 4、发送数据
     */
    private class MyChannel implements Runnable{
        private DataInputStream dis;
        private DataOutputStream dos;
        private boolean isRunning = true;

        public MyChannel(Socket client) {
            try {
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dis,dos);
                isRunning = false;
            }
        }
        /**
         * 读取数据
         * @return
         */
        private String receive(){
            String msg = "";
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dis);
                isRunning = false;
                all.remove(this);//移除自身
            }
            return msg;
        }
        /**
         * 发送数据
         */
        private void send(String msg){
            if(null==msg || msg.equals("")){
                return;
            }
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                //e.printStackTrace();
                CloseUtil.closeAll(dos);
                isRunning = false;
                all.remove(this);//移除自身
            }
        }
        /**
         * 发送给其它客户端
         */
        private void sendOthers(){
            String msg = this.receive();
            //遍历容器
            for (MyChannel other : all) {
                if(other==this){
                    continue;
                }
                //发送给其它客户端
                other.send(msg);
            }
        }

        @Override
        public void run() {
            while(isRunning){
                sendOthers();
            }
        }
    }
}
package com.test.net.tcp.chat;

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 console;
    //管道输出流
    private DataOutputStream dos;
    //控制线程
    private boolean isRunning = true;

    public Send() {
        console = new BufferedReader(new InputStreamReader(System.in));
    }
    public Send(Socket client) {
        this();
        try {
            dos = new DataOutputStream(client.getOutputStream());
        } catch (IOException e) {
            //e.printStackTrace();
            isRunning = false;
            CloseUtil.closeAll(dos,console);
        }
    }
    //1、从控制台接收数据
    private String getMsgFromConsole(){
        try {
            return console.readLine();
        } catch (IOException e) {
            //e.printStackTrace();
        }
        return "";
    }
    /**
     * 1、从控制台接收数据
     * 2、发送数据
     */
    public void send(){
        String msg = getMsgFromConsole();
        if(null!=msg && !msg.equals("")){
            try {
                dos.writeUTF(msg);
                dos.flush();//强制刷新
            } catch (IOException e) {
                //e.printStackTrace();
                isRunning = false;
                CloseUtil.closeAll(dos,console);
            }
        }
    }

    @Override
    public void run() {
        while(isRunning){
            send();
        }
    }
}
package com.test.net.tcp.chat;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
 * 接收数据线程
 */
public class Receive implements Runnable {
    //输入流
    private DataInputStream dis;
    //线程标识
    private boolean isRunning = true;

    public Receive() {
    }
    public Receive(Socket client){
        try {
            dis = new DataInputStream(client.getInputStream());
        } catch (IOException e) {
            //e.printStackTrace();
            isRunning = false;
            CloseUtil.closeAll(dis);
        }
    }
    /**
     * 接收数据
     */
    public String receive(){
        String msg = "";
        try {
            msg = dis.readUTF();
        } catch (IOException e) {
            //e.printStackTrace();
            isRunning = false;
            CloseUtil.closeAll(dis);
        }
        return msg;
    }
    @Override
    public void run() {
        while(isRunning){
            System.out.println(receive());
        }
    }
}
package com.test.net.tcp.chat;

import java.io.Closeable;
import java.io.IOException;
/**
 * 关闭流的方法
 */
public class CloseUtil {
    public static void closeAll(Closeable...io){
        for (Closeable temp : io) {
            if(null!=temp){
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
里面包含聊天室客户端和服务器端的源文件和一份完整的设计报告。 一、 系统概要 本系统能实现基于VC++的网络聊天室系统。有单独的客户端、服务器端。 服务器应用程序能够接受来自客户端的广播,然后向客户端发送本机的IP与服务端口,让客户端接入到服务器进行聊天,检测用户名是否合法(重复),服务器责接收来自客户端的聊天信息,并根据用户的需求发送给指定的人或所有人,能够给出上线下线提示。客户端能够发出连接请求,能编辑发送信息,可以指定发给单人或所有人,能显示聊天人数,上线下线用户等。 二、 通信规范的制定 服务请求规范: 服务器端: (1) 创建一个UDP的套接字,接受来自客户端的广播请求,当请求报文内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”时,接受请求,给客户端发送本服务器TCP聊天室的端口号。 (2) 创建一个主要的TCP协议的套接字负责客户端TCP连接 ,处理它的连接请求事件。 (3)在主要的TCP连接协议的套接字里面再创建TCP套接字保存到动态数组里,在主要的套接字接受请求后 ,就用这些套接字和客户端发送和接受数据。 客户端: (1) 当用户按“连接”按钮时,创建UDP协议套接字,给本地计算机发广播,广播内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”。 (2)当收到服务器端的回应,收到服务器发来的端口号后,关闭UDP连接。根据服务器的IP地址和端口号重新创建TCP连接。 故我思考:客户端一定要知道服务器的一个端口,我假设它知道服务器UDP服务的端口,通过发广播给服务器的UDP服务套接字,然后等待该套接字发回服务器TCP聊天室服务的端口号,IP地址用ReceiveForom也苛刻得到。 通信规范 通信规范的制定主要跟老师给出的差不多,并做了一小点增加: (增加验证用户名是否与聊天室已有用户重复,在服务器给客户端的消息中,增加标志0) ① TCP/IP数据通信 --- “聊天”消息传输格式 客户机 - 服务器 (1)传输“用户名” STX+1+用户名+ETX (2) 悄悄话 STX+2+用户名+”,”+内容+ETX (3) 对所有人说 STX+3+内容+ETX 服务器- 客户机 (0)请求用户名与在线用户名重复 //改进 STX+0+用户名+EXT (1)首次传输在线用户名 STX+1+用户名+ETX (2)传输新到用户名 STX+2+用户名+ETX (3)传输离线用户名 STX+3+用户名+ETX (4)传输聊天数据 STX+4+内容+ETX (注:STX为CHR(2),ETX 为CHR(3)) 三、 主要模块的设计分析 四、 系统运行效果 (要求有屏幕截图) 五、 心得与体会

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值