TCP套接字实现多用户对话

功能详细描述:

客户端程序1:TCPclient.java(用于网络接收和发送)

客户端程序2:TCPclientThreadJFrame.java(多线程接收来自服务器的信息)

服务器程序1:TCPThreadServer.java(多用户服务器,实现多用户连接)

服务器程序2:GroupServer.java(多用户对话)

1. TCPclient.java

import java.io.*;
import java.net.*;

/**
 *
 * @author 13108
 */
public class TCPclient {

    private Socket socket = null;
    private PrintWriter pw = null;
    private BufferedReader br = null;

    public TCPclient(String ip, String port) throws IOException {
        //向服务进程发起TCP三次握手连接
        socket = new Socket(ip, Integer.parseInt(port));

        OutputStream socketOut = socket.getOutputStream();
        pw = new PrintWriter(new OutputStreamWriter(socketOut, "GB2312"), true);
        //得到网络输出字节流地址,并装饰成网络输出字符流

        InputStream socketIn = socket.getInputStream();
        br = new BufferedReader(new InputStreamReader(socketIn, "GB2312"));
        //得到网络输入字节流地址,并装饰成网络输入字符流
    }
    
    //定义网络信息发送方法供外部调用
    public void send(String msg) {
        //写入网卡输出流,由系统调用底层函数,经网卡发送。
        pw.println(msg);
    }

    //定义网络信息接收方法供外部调用
    public String receive() {
        String msg;
        try {
            //接收一行信息,阻塞语句
            msg = br.readLine();
        } catch (IOException ex) {
            msg = null;
        }

        return msg;
    }

    public void close() {

        try {
            if (socket != null) {
                socket.close();//断开TCP连接
            }
        } catch (IOException ex) {
           ex.printStackTrace();
        }
    }
}

2. TCPclientThreadJFrame.java

(1)利用NetBeans新建JFrame窗体程序,使用组件标签、文本字段、文本区域、按钮

(2)定义TCPclient对象

public TCPclient ec;

 

(3)双击连接按钮,添加事件

//获取ip和端口
String ip = jTextField1.getText();
String port = jTextField2.getText();
try {
        ec = new TCPclient(ip, port);//ec为TCPclient对象,全局对象
        jTextArea1.append("服务器连接成功.\r\n");
        //用一个线程专门用于接收信息
        Thread receiver = new Thread() {
            @Override
            public void run() {
                String msg = null;
                while ((msg = ec.receive()) != null) {
                    jTextArea1.append(msg + "\n");
                }
                    jTextArea1.append("对话已关闭!\n");
           }
        };
        //启动线程
        receiver.start();
} catch (IOException ex) {
    jTextArea1.append("服务器连接失败.\r\n");
  }

(4)发送按钮

//获取录入信息
String msg = jTextField3.getText();
//调用TCPclient中的send()方法
ec.send(msg);
//将信息录入区设为空白输入
jTextField3.setText(null);

(5)退出按钮

ec.close();
System.exit(0);

3. TCPThreadServer.java

import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 * @author 13108
 */
public class TCPThreadServer {

    private final int port = 8008;
    private ServerSocket serverSocket;
    private ExecutorService executorService;//线程池
    private final int POOL_SIZE = 15;//单个CPU时线程池中工作线程的数目

    public TCPThreadServer() throws IOException {
        serverSocket = new ServerSocket(8008);
        //创建线程池
        //Runtime的availableProcessors()方法返回当前系统的CPU的数目
        //系统的CPU越多,线程池中工作线程的数目也应该越多
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
        System.out.println("多用户服务器启动");

    }

    public void service() {
        while (true) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
                //阻塞语句,监听并等待客户发起连接,有连接请求就生成一个套接字。

                //接受一个客户请求,从线程池中拿出一个线程专门处理该客户.
                executorService.execute(new Handler(socket));

            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

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

//定义内部类,实现线程接口
class Handler implements Runnable {

    private Socket socket;

    public Handler(Socket socket) {
        this.socket = socket;
    }
    //获取字符输出流
    private PrintWriter putWriter(Socket socket) throws IOException {
        OutputStream socketOut = socket.getOutputStream();
        return new PrintWriter(new OutputStreamWriter(socketOut, "GB2312"), true);
    }
    //获取字符输入流
    private BufferedReader getReader(Socket socket) throws IOException {
        InputStream socketIn = socket.getInputStream();
        return new BufferedReader(new InputStreamReader(socketIn, "GB2312"));
    }

    //覆盖线程体
    public void run() {
        try {
            System.out.println("New income:" + socket.getInetAddress());//本地服务器观测台显示请求的用户信息。
            BufferedReader br = getReader(socket);//字节装饰成字符流
            PrintWriter pw = putWriter(socket);//字节装饰成字符流
            String msg;
            while ((msg = br.readLine()) != null) {
                pw.println("来自多线程服务器:" + msg);//向输出流中输出一行字符串
                //信息中包含bye结束对话
                if (msg.contains("bye".subSequence(0, 2))) {
                    System.out.println(socket.getInetAddress() + ":Exit");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

4. GroupServer.java

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 * @author 13108
 */
public class GroupServer {

    private final int port = 8008;
    private ServerSocket serverSocket;
    private ExecutorService executorService;//线程池
    private final int POOL_SIZE = 15;//单个CPU时线程池中工作线程的数目
    private static Set<Socket> Members;//全局变量,在线组员集合

    public GroupServer() throws IOException {
        serverSocket = new ServerSocket(8008);
        
        //实例化在线组员集合
        Members=new HashSet<Socket>();
        
        
        //创建线程池
        //Runtime的availableProcessors()方法返回当前系统的CPU的数目
        //系统的CPU越多,线程池中工作线程的数目也应该越多
        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
        System.out.println("多用户服务器启动");

    }

    //单客户版本,即每次只能同时和一个客户建立通信连接。
    public void service() {
        while (true) {
            Socket socket = null;

            try {
                socket = serverSocket.accept();
                
                Members.add(socket);
                //阻塞语句,监听并等待客户发起连接,有连接请求就生成一个套接字。

                //接受一个客户请求,从线程池中拿出一个线程专门处理该客户.
                executorService.execute(new Handler1(socket));

            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
    
    //定义群组消息发送方法
    public static void sendToAllMembers(String msg) throws IOException{
        PrintWriter pw;
        Socket tempSocket;
        OutputStream out;
        //遍历在线成员set集合
        Iterator it=Members.iterator();
        while(it.hasNext()){
            //取出一个成员
           tempSocket=(Socket)it.next();
           //得到输出流
           out=tempSocket.getOutputStream();
           //装饰成字符流
           pw=new PrintWriter(new OutputStreamWriter(out,"GB2312"),true);
           //发送聊天信息给成员
           pw.println(msg);
           
        }
    }
    
    //定义组员退出方法
    public static void removeMember(Socket socket){
        Members.remove(socket);
    }

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

//定义内部类,实现线程接口
class Handler1 implements Runnable {

    private Socket socket;

    public Handler1(Socket socket) {
        this.socket = socket;
    }

    private PrintWriter putWriter(Socket socket) throws IOException {

        OutputStream socketOut = socket.getOutputStream();
        return new PrintWriter(new OutputStreamWriter(socketOut, "GB2312"), true);
    }

    private BufferedReader getReader(Socket socket) throws IOException {
        InputStream socketIn = socket.getInputStream();
        return new BufferedReader(new InputStreamReader(socketIn, "GB2312"));
    }
    
    //覆盖线程体
    public void run() {
        try {
            System.out.println("New income:" + socket.getInetAddress());//本地服务器观测台显示请求的用户信息。
            BufferedReader br = getReader(socket);//字节装饰成字符流
            PrintWriter pw = putWriter(socket);//字节装饰成字符流
            String msg;
            while ((msg = br.readLine()) != null) {
                GroupServer.sendToAllMembers(msg);
                if (msg.contains("bye".subSequence(0, 2))) {
                    System.out.println(socket.getInetAddress() + ":Exit");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex) {
                   ex.printStackTrace();
                }
            }
        }
    }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值