功能详细描述:
客户端程序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();
}
}
}
}
}