Java实现简单的Socket服务器(源码公开)

服务器端使用ServerSocket类,需要调用accept()方法阻塞线程,所以不应放在main方法中,我们新建一个ServerListener类用来监听客户端的连接。

MyServer类

package socket.server;

public class MyServerSocket {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
<span style="white-space:pre">		</span>//匿名类调用ServerListener的run()方法
		new ServerListener().start();
	}

}

ServerListener类,继承Thread类

package socket.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerListener extends Thread {

	@SuppressWarnings("resource")
	@Override
	public void run() {
		ServerSocket mServerSocket = null;
		Socket socket = new Socket();
		// 新建服务端并且指定端口号
		try {
			mServerSocket = new ServerSocket(11111);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		while (true) {
			try {

				// 将服务端接收到的客户端Socket传给socket,用来与该客户端进行通信
				socket = mServerSocket.accept();
				// 将连接的socket传给ChatSocket(ChatSocket实现对客户端的数据发送与接收)
				ChatSocket mChatSocket = new ChatSocket(socket);
				// 将ChatSocket放入ChatManager中进行管理,传入ChatManager的Vector泛型数组中
				ChatManager.getChatManager().add_ChatManager(mChatSocket);

				mChatSocket.start();
				System.out.println("连接成功");

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
}

然后是ChatSocket类,也是继承Thread类,用来接收客户端发送给服务器的消息,并且发送消息给其他客户端。

package socket.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ChatSocket extends Thread {
	private Socket mSocket;// 服务器Socket既是操作客户端的object

	public ChatSocket(Socket socket) {
		this.mSocket = socket;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		try {
			// 获取客户端发送来的消息
			InputStreamReader mInputStreamReader = new InputStreamReader(
					mSocket.getInputStream(),"utf-8");
			BufferedReader bfr = new BufferedReader(mInputStreamReader);
			String text = null;

			while ((text = bfr.readLine()) != null) {
				// 向已连接的所有的客户端发送消息
//				ChatManager.getChatManager().pulish(this, text);
				System.out.println(text);
			}
			bfr.close();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	// 用来给客户端发送消息的方法
	public void out(String out_string) {
		OutputStreamWriter mOutputStreamWriter;
		try {
			mOutputStreamWriter = new OutputStreamWriter(
					mSocket.getOutputStream());
			BufferedWriter mBufferedWriter = new BufferedWriter(
					mOutputStreamWriter);
			mBufferedWriter.write(out_string);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

因为服务器要给多个客户端发送消息,所以需要新建一个ChatManager类,用来管理连接到服务器的客户端,将连接到服务器的客户端Socket传入Vector泛型数组。ChatManger类不需要继承Thread类,这里它起到一个管理工具的作用。

package socket.server;

import java.util.Vector;

public class ChatManager {

	// 将ChatManager单例化
	private ChatManager() {
		// 此方法将使得其他类中不能对ChatManager实例化
	}

	private static final ChatManager M_CHAT_MANAGER = new ChatManager();// 保证ChatManager只有一个实例

	// 一般工具类都使用static属性
	public static ChatManager getChatManager() {
		// 提供给其他类使用ChatManager
		return M_CHAT_MANAGER;
	}

	// 存储ChatSocket的泛型数组
	Vector<ChatSocket> vector_ChatSockets = new Vector<>();

	// 当有新的客户端连接时,添加进vector
	public void add_ChatManager(ChatSocket chatSocket) {
		vector_ChatSockets.add(chatSocket);
	}

	// 收集某个客户端(cs)的信息,并发送给更多的客户端
	public void pulish(ChatSocket cs, String out) {
		for (int i = 0; i < vector_ChatSockets.size(); i++) {// 遍历ChatSocket
			// 获取遍历的ChatSocket在Vector中的下标
			ChatSocket csChatSocket = vector_ChatSockets.get(i);
			// 判断遍历的ChatSocket是否为发送信息到服务器的客户端
			if (!cs.equals(csChatSocket)) {
				csChatSocket.out(out);
			}
		}
	}
}


总结:

Socket通信其实就是操作Socket对象本身,服务器的ServerSocket也是起到一个转接的作用(把监听到的的客户端Socket传给服务器本身的Socket),然后Socket就相当一个中转站,去操控输入输出流,和其他的一些方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值