欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【java的socket编程】用socket进行多线程客户端-服务器通信

程序员文章站 2022-03-24 11:37:42
...

文件目录:
【java的socket编程】用socket进行多线程客户端-服务器通信
chartserver:


public class ChatServer {
	private static final int SOCKET_PORT = 52000;
	public static ArrayList<SocketBean> mSocketList = new ArrayList<SocketBean>();

	private void initServer() {
		try {
			// 创建一个ServerSocket,用于监听客户端Socket的连接请求
			ServerSocket server = new ServerSocket(SOCKET_PORT);
			while (true) {
				// 每当接收到客户端的Socket请求,服务器端也相应的创建一个Socket
				SocketBean socket = new SocketBean(DateUtil.getTimeId(), server.accept());
				mSocketList.add(socket);
				// 每连接一个客户端,启动一个ServerThread线程为该客户端服务
				new Thread(new ServerThread(socket)).start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		ChatServer server = new ChatServer();
		server.initServer();
	}
}

ServerThread


public class ServerThread implements Runnable {
	private SocketBean mSocket = null;
	private BufferedReader mReader = null;

	public ServerThread(SocketBean mSocket) throws IOException {
		this.mSocket = mSocket;
		mReader = new BufferedReader(new InputStreamReader(mSocket.socket.getInputStream()));
	}

	@Override
	public void run() {
		try {
			String content = null;
			// 循环不断地从Socket中读取客户端发送过来的数据
			while ((content = mReader.readLine()) != null) {
				System.out.println("content="+content);
				int pos = content.indexOf("|");
				// 包头格式为:动作名称|设备编号|昵称|时间|对方设备编号
				String head = content.substring(0, pos);
				String body = content.substring(pos+1);
				String[] splitArray = head.split(",");
				String action = splitArray[0];
				System.out.println("action="+action);
				if (action.equals("LOGIN")) {
					login(splitArray[1], splitArray[2], splitArray[3]);
				} else if (action.equals("LOGOUT")) {
					logout(splitArray[1]);
					break;
				} else if (action.equals("SENDMSG")) {
					sendmsg("RECVMSG", splitArray[2], splitArray[4], splitArray[1], body);
				} else if (action.equals("GETLIST")) {
					getlist(splitArray[1]);
				} else if (action.equals("SENDPHOTO")) {
					sendmsg("RECVPHOTO", splitArray[2], splitArray[4], splitArray[1], body);
				} else if (action.equals("SENDSOUND")) {
					sendmsg("RECVSOUND", splitArray[2], splitArray[4], splitArray[1], body);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void login(String deviceId, String nickName, String loginTime) throws IOException {
		for (int i=0; i<ChatServer.mSocketList.size(); i++) {
			SocketBean item = ChatServer.mSocketList.get(i);
			if (item.id.equals(mSocket.id)) {
				item.deviceId = deviceId;
				item.nickName = nickName;
				item.loginTime = loginTime;
				ChatServer.mSocketList.set(i, item);
				break;
			}
		}
	}
	
	private String getFriend() {
		String friends = "GETLIST,";
		for (SocketBean item : ChatServer.mSocketList) {
			if (item.deviceId!=null && item.deviceId.length()>0) {
				String friend = String.format("|%s,%s,%s", item.deviceId, item.nickName, item.loginTime);
				friends += friend;
			}
		}
		return friends;
	}
	
	private void getlist(String deviceId) throws IOException {
		for (int i=0; i<ChatServer.mSocketList.size(); i++) {
			SocketBean item = ChatServer.mSocketList.get(i);
			if (item.id.equals(mSocket.id) && item.deviceId.equals(deviceId)) {
				PrintStream ps = new PrintStream(item.socket.getOutputStream());
				ps.println(getFriend());
				break;
			}
		}
	}
	
	private void logout(String deviceId) throws IOException {
		for (int i=0; i<ChatServer.mSocketList.size(); i++) {
			SocketBean item = ChatServer.mSocketList.get(i);
			if (item.id.equals(mSocket.id) && item.deviceId.equals(deviceId)) {
				PrintStream ps = new PrintStream(item.socket.getOutputStream());
				ps.println("LOGOUT,|");
				item.socket.close();
				ChatServer.mSocketList.remove(i);
				break;
			}
		}
	}

	private void sendmsg(String respAction, String otherName, String otherId, String selfId, String message) throws IOException {
		for (int i=0; i<ChatServer.mSocketList.size(); i++) {
			SocketBean item = ChatServer.mSocketList.get(i);
			if (item.deviceId.equals(otherId)) {
				String content = String.format("%s,%s,%s,%s|%s", 
						respAction, selfId, otherName, DateUtil.getNowTime(), message);
				System.out.println("resp="+content);
				PrintStream ps = new PrintStream(item.socket.getOutputStream());
				ps.println(content);
				break;
			}
		}
	}

}

socketbean:


public class SocketBean {
	public String id;
	public Socket socket;
	public String deviceId;
	public String nickName;
	public String loginTime;
	
	public SocketBean(String id, Socket socket) {
		this.id = id;
		this.socket = socket;
		this.deviceId = "";
		this.nickName = "";
		this.loginTime = "";
	}

}

TestServer:


public class TestServer {
	private static final int SOCKET_PORT = 51000;

	private void initServer() {
		try {
			// 创建一个ServerSocket,用于监听客户端Socket的连接请求
			ServerSocket server = new ServerSocket(SOCKET_PORT);
			while (true) {
				Socket socket = server.accept();
				new Thread(new ServerThread(socket)).start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		TestServer server = new TestServer();
		server.initServer();
	}
	
	private class ServerThread implements Runnable {
		private Socket mSocket;
		private BufferedReader mReader;
		
		public ServerThread(Socket socket) throws IOException {
			mSocket = socket;
			mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
		}

		@Override
		public void run() {
			try {
				String content = null;
				// 循环不断地从Socket中读取客户端发送过来的数据
				while ((content = mReader.readLine()) != null) {
					System.out.println("收到客户端消息:"+content);
					PrintStream ps = new PrintStream(mSocket.getOutputStream());
					ps.println("hi,很高兴认识你");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

客户端:


public class MessageTransmit implements Runnable {
	private static final String TAG = "MessageTransmit";
	// 以下为Socket服务器的ip和端口,根据实际情况修改
	private static final String SOCKET_IP = "192.168.0.212";
	private static final int SOCKET_PORT = 51000;

	private Socket mSocket;
	private BufferedReader mReader = null;
	private OutputStream mWriter = null;

	@Override
	public void run() {
		mSocket = new Socket();
		try {
			mSocket.connect(new InetSocketAddress(SOCKET_IP, SOCKET_PORT), 3000);
			mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
			mWriter = mSocket.getOutputStream();
			// 启动一条子线程来读取服务器的返回数据
			new RecvThread().start();
			Looper.prepare();
			Looper.loop();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 定义接收UI线程的Handler对象,App向后台服务器发送消息
	public Handler mRecvHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			Log.d(TAG, "handleMessage: "+msg.obj);
			// 换行符相当于回车键,表示我写好了发出去吧
			String send_msg = msg.obj.toString()+"\n";
			try {
				mWriter.write(send_msg.getBytes("utf8"));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};

	// 定义消息接收子线程,App从后台服务器接收消息
	private class RecvThread extends Thread {
		@Override
		public void run() {
			try {
				String content = null;
				while ((content = mReader.readLine()) != null) {
					// 读取到来自服务器的数据
					Message msg = Message.obtain();
					msg.obj = content;
					SocketActivity.mHandler.sendMessage(msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}

public class ClientThread implements Runnable {
	private static final String TAG = "ClientThread";
	private static final String SOCKET_IP = "192.168.253.1";
	//private static final String SOCKET_IP = "192.168.0.212";
	private static final int SOCKET_PORT = 52000;
	public static final String REQUEST_URL = "http://192.168.253.1:8080/UploadTest";
	private Context mContext;
	private Socket mSocket;
	public Handler mRecvHandler;
	private BufferedReader mReader = null;
	private OutputStream mWriter = null;
	
	public static String ACTION_RECV_MSG = "com.example.network.RECV_MSG";
	public static String ACTION_GET_LIST = "com.example.network.GET_LIST";
	public static String CONTENT = "CONTENT";
	public static String SPLIT_LINE = "|";
	public static String SPLIT_ITEM = ",";
	public static String LOGIN = "LOGIN";
	public static String LOGOUT = "LOGOUT";
	public static String SENDMSG = "SENDMSG";
	public static String RECVMSG = "RECVMSG";
	public static String GETLIST = "GETLIST";
	public static String SENDPHOTO = "SENDPHOTO";
	public static String RECVPHOTO = "RECVPHOTO";
	public static String SENDSOUND = "SENDSOUND";
	public static String RECVSOUND = "RECVSOUND";

	public ClientThread(Context context) {
		mContext = context;
	}

	@Override
	public void run() {
		Log.d(TAG, "run");
		mSocket = new Socket();
		try {
			Log.d(TAG, "connect");
			mSocket.connect(new InetSocketAddress(SOCKET_IP, SOCKET_PORT), 3000);
			mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
			Log.d(TAG, "getOutputStream");
			mWriter = mSocket.getOutputStream();
			Log.d(TAG, "RecvThread");
			// 启动一条子线程来读取服务器相应的数据
			new RecvThread().start();
			Looper.prepare();
			// 定义接收UI线程的Handler对象,App向后台服务器发送消息
			// 如果是在Application中启动线程,则mRecvHandler要在线程启动后才能初始化
			// 并且要在Looper.prepare之后执行初始化动作
			mRecvHandler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					// 接收到UI线程的用户输入的数据
					try {
						mWriter.write(msg.obj.toString().getBytes("utf8"));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			Looper.loop();
		} catch (Exception e) {
			e.printStackTrace();
			notify(99, e.getMessage());
		}
	}

	// 定义消息接收子线程,App从后台服务器接收消息
	private class RecvThread extends Thread {
		@Override
		public void run() {
			String content = null;
			try {
				while ((content = mReader.readLine()) != null) {
					// 读取到来自服务器的数据之后,发送消息通知
					ClientThread.this.notify(0, content);
				}
			} catch (Exception e) {
				e.printStackTrace();
				ClientThread.this.notify(97, e.getMessage());
			}
		}
	}

	private void notify(int type, String message) {
		if (type == 99) {
			String content = String.format("%s%s%s%s", "ERROR", SPLIT_ITEM, SPLIT_LINE, message);
			Intent intent1 = new Intent(ACTION_RECV_MSG);
			intent1.putExtra(CONTENT, content);
			mContext.sendBroadcast(intent1);
			Intent intent2 = new Intent(ACTION_GET_LIST);
			intent2.putExtra(CONTENT, content);
			mContext.sendBroadcast(intent2);
		} else {
			int pos = message.indexOf(SPLIT_LINE);
			String head = message.substring(0, pos - 1);
			String[] splitArray = head.split(SPLIT_ITEM);
			String action = "";
			if (splitArray[0].equals(RECVMSG) 
					|| splitArray[0].equals(RECVPHOTO) 
					|| splitArray[0].equals(RECVSOUND)) {
				action = ACTION_RECV_MSG;
			} else if (splitArray[0].equals(GETLIST)) {
				action = ACTION_GET_LIST;
			}
			Log.d(TAG, "action=" + action + ", message=" + message);
			Intent intent = new Intent(action);
			intent.putExtra(CONTENT, message);
			mContext.sendBroadcast(intent);
		}
	}

}