socket通信例子_服务端写客户端读多线程写法

1、主程序
/**
	 * 主程序启动入口
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		ctx = new ClassPathXmlApplicationContext(APPLICATION_XML_FILE);
		ctx.start();
		//
		SingletonMessagePush instance=SingletonMessagePush.getInstance();//单例服务类
		try {
			ServerSocket serverSocket=new ServerSocket(getMessagePushPort());//serverSocket,只负责监听客户端连接,一旦连接成功,服务端会新建一个socket负责与客户端通信
			while(true){//不断监听客户端连接
				Socket socket = serverSocket.accept();//返回一个客户端的Socket对象实例
				//
				System.out.println("【发现客户端连接>>>>>>】");
				if(null!=socket){
					CopyOnWriteArrayList<Socket> oldList=instance.getSocket();
	        		for (Socket so : oldList) {
	        			if(so.isConnected()==false||so.isClosed()==true){
	        				instance.getSocket().remove(so);//移除
	        				System.out.println(so.getInetAddress()+"从socket客户端集合移除。");
	        			}
	        		}
	        		if(socket.isConnected()==true&&socket.isClosed()==false){
		        		instance.getSocket().add(socket);//添加客户端socket
						System.out.println("添加客户端:"+socket.getInetAddress()+",当前有效客户端总数:"+instance.getSocket().size());
	        		}
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("主程序启动时服务端socket异常");
		}
	}


2、推送消息单例类
package com.vxichina.cluster.persistence.core;

import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author mingfeng.wang
* @date 2016年3月15日 
* @time 上午10:54:18
* 向录屏程序推送消息的类
*/
public class SingletonMessagePush {
	//有效客户端socket连接集合
	private CopyOnWriteArrayList<Socket> socket=new CopyOnWriteArrayList<Socket>();
	//线程池
	private ExecutorService threadPool=Executors.newCachedThreadPool();
	//private构造函数
	private SingletonMessagePush(){
		
	}
	private static SingletonMessagePush instance;
	//对外访问方法
	public static SingletonMessagePush getInstance(){
		if(null==instance){
			instance=new SingletonMessagePush();
		}
		return instance;
	}
	/**
	 * 推送消息的主方法
	 * @param dataStr
	 */
	public void doMain(String dataStr){
		try {
	         if(null!=dataStr&&!"".equals(dataStr)){
	        	if(null!=socket&&socket.size()>0){
	        		//#s 给所有有效连接的客户端推送消息
	        		for (Socket sc : this.getSocket()) {
	        			final String message=dataStr;
	        			final Socket clientSocket=sc;
	        			if(sc.isConnected()==true&&sc.isClosed()==false){
	        				//new Thread(new Task(sc,dataStr)).start();//多线程
	        				Thread.sleep(0);
	        				//线程池方式
	        				threadPool.execute(new Runnable() {
								@Override
								public void run() {
									try {
										System.out.println("当前线程name="+Thread.currentThread().getName()+",  id="+Thread.currentThread().getId());
										// 服务端写数据
										Writer writer = new OutputStreamWriter(clientSocket.getOutputStream());
										writer.write(message);
										writer.flush();
										System.out.println("成功给客户端"+clientSocket.getInetAddress()+"推送消息。消息内容:\n"+message);
										//writer.close();//不能关闭,关闭会导致客户端close一段时间
									}catch (Exception e) {
										System.out.println("给客户端"+clientSocket.getInetAddress()+"推送消息异常。");
									}
								}
							});
	        			}
					}
	        		//#e
				}else{
					System.out.println("暂无客户端连接。");
				}
	         }
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("doMain推送消息异常。");
		}
	}
	
	
	public CopyOnWriteArrayList<Socket> getSocket() {
		return socket;
	}
	public void setSocket(CopyOnWriteArrayList<Socket> socket) {
		this.socket = socket;
	}


}


3、模拟客户端访问
public class ClientSocketTest {

	public static void main(String[] args) {
		String host="192.68.19.64";//自定义
		int port=9080;
		try {
			Socket client = new Socket(host, port);
			while(true){
				System.out.println("【>>>>>>客户端正在监听>>>>>>】,isConnected="+client.isConnected()+",isClosed="+client.isClosed());
				// 客户端读数据
				Reader reader = new InputStreamReader(client.getInputStream());
				char chars[] = new char[64];
				int len;
				StringBuffer sb = new StringBuffer();
				while ((len = reader.read(chars)) != -1) {
					sb.append(new String(chars, 0, len));
				}
				System.out.println("客户端读数据结束。" );
				reader.close();
				//client.close();
			
			}
		}catch(java.net.SocketException e){
			if(e.getMessage().equals("Connection reset")){
				System.out.println("连接被重置,服务端已关闭。");
			}
		}catch (Exception e) {
			e.printStackTrace();
			System.out.println("客户端其它异常。");
		}
	}
}


===============================================================================
1、服务端监听端口
private static final String appConfigFile = "/app-config.properties";
public static void main(String[] args) {
		SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance();
		try {
			//System.out.println("端口:"+getMessagePushPort());
			ServerSocket serverSocket=new ServerSocket(getMessagePushPort());
			singletonServerSocket.setServerSocket(serverSocket);//serverSocket
			while(true){
				Socket socket = serverSocket.accept();//监听,接受客户端连接
				if(null!=socket){
					singletonServerSocket.setSocket(socket);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 从Properties文件中获取推送信息需要监听的socket通信端口
	 * @return
	 */
	public static int getMessagePushPort(){
		int port=0;
		Properties properties = new Properties();
		try {
			properties.load(Object.class.getResourceAsStream(appConfigFile));
		} catch (IOException e) {
			e.printStackTrace();
		}
	    port=Integer.valueOf(properties.getProperty("messagePushPort").trim());
		return port;
	}


2、调用
SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance();//单例类
//推送socket消息到客户端
singletonServerSocket.doMain(str.toString());


3、SingletonServerSocket 单例类-服务端写数据
public class SingletonServerSocket {
	private ServerSocket serverSocket;
	private Socket socket;
	//private构造函数
	private SingletonServerSocket(){
		
	}
	private static SingletonServerSocket instance;
	//对外访问方法
	public static SingletonServerSocket getInstance(){
		if(null==instance){
			instance=new SingletonServerSocket();
		}
		return instance;
	}
	/**
	 * 推送消息的主方法
	 * @param dataStr
	 */
	public void doMain(String dataStr){
		try {
	         if(null!=dataStr&&!"".equals(dataStr)){
	        	 if(null!=socket){
	        		 	new Thread(new Task(socket,dataStr)).start();//多线程
					}else{
						System.out.println("暂无客户端连接,无法完成写操作。");
					}
	         }
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	 /**
	  * 用来处理socket请求的多线程
	  * 
	  *
	  */
	static class Task implements Runnable {

		private Socket socket2;
		private String data;

		public Task(Socket socket, String data) {
			this.socket2 = socket;
			this.data = data;
		}

		public void run() {
			try {
				handleSocket();// 处理客户端socket
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		/**
		 * 跟客户端Socket进行通信
		 * 
		 */
		private void handleSocket(){
			try {
				// 服务端写数据
				Writer writer = new OutputStreamWriter(socket2.getOutputStream());
				writer.write(data);
				System.out.println("服务端写数据:" + data);
				writer.flush();
				//writer.close();
			} catch (java.net.SocketException e) {
				System.out.println("无法找到写数据的客户端!");
			} catch (Exception e) {
				System.out.println("服务端写数据错误!");
			}
			// socket2.close();//服务端socket,不能关闭
		}
	}
	public ServerSocket getServerSocket() {
		return serverSocket;
	}
	public void setServerSocket(ServerSocket serverSocket) {
		this.serverSocket = serverSocket;
	}
	public Socket getSocket() {
		return socket;
	}
	public void setSocket(Socket socket) {
		this.socket = socket;
	}

}

4、客户端读数据
public class ClientSocket {

	public static void main(String[] args) {
		String host="192........";
		int port=9099;
		try {
			Socket client = new Socket(host, port);
			while(true){
				System.out.println("client request...");
				
				if(client.isClosed()){
					client = new Socket(host, port);
				}
				// 客户端读数据
				Reader reader = new InputStreamReader(client.getInputStream());
				char chars[] = new char[64];
				int len;
				StringBuffer sb = new StringBuffer();
				while ((len = reader.read(chars)) != -1) {
					sb.append(new String(chars, 0, len));
				}
				System.out.println("客户端读数据:" + sb);
				reader.close();
				client.close();
			
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自franciswmf.iteye.com/blog/2283579