Java Socket实现多个客户端连接同一个服务端

使用Socket实现多个客户端和同一客户端通讯;首先客户端连接服务端发送一条消息,服务端接收到消息后进行处理,完成后再回复客户端一条消息。本人通过自己的思维编写了一份服务端和客户端实现的代码,望能与大家相互学习,共同进步。


  服务端代码

/**
 * Socket服务端<br>
 * 功能说明:
 * 
 * @author 大智若愚的小懂
 * @Date 2016年8月30日
 * @version 1.0
 */
public class Server {

	/**
	 * 入口
	 * 
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// 为了简单起见,所有的异常信息都往外抛
		int port = 8899;
		// 定义一个ServiceSocket监听在端口8899上
		ServerSocket server = new ServerSocket(port);
		System.out.println("等待与客户端建立连接...");
		while (true) {
			// server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
			Socket socket = server.accept();
			/**
			 * 我们的服务端处理客户端的连接请求是同步进行的, 每次接收到来自客户端的连接请求后,
			 * 都要先跟当前的客户端通信完之后才能再处理下一个连接请求。 这在并发比较多的情况下会严重影响程序的性能,
			 * 为此,我们可以把它改为如下这种异步处理与客户端通信的方式
			 */
			// 每接收到一个Socket就建立一个新的线程来处理它
			new Thread(new Task(socket)).start();

		}
		// server.close();
	}

	/**
	 * 处理Socket请求的线程类
	 */
	static class Task implements Runnable {

		private Socket socket;

		/**
		 * 构造函数
		 */
		public Task(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				handlerSocket();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		/**
		 * 跟客户端Socket进行通信
		 * 
		 * @throws IOException
		 */
		private void handlerSocket() throws Exception {
			// 跟客户端建立好连接之后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
			/**
			 * 在从Socket的InputStream中接收数据时,像上面那样一点点的读就太复杂了,
			 * 有时候我们就会换成使用BufferedReader来一次读一行
			 * 
			 * BufferedReader的readLine方法是一次读一行的,这个方法是阻塞的,直到它读到了一行数据为止程序才会继续往下执行,
			 * 那么readLine什么时候才会读到一行呢?直到程序遇到了换行符或者是对应流的结束符readLine方法才会认为读到了一行,
			 * 才会结束其阻塞,让程序继续往下执行。
			 * 所以我们在使用BufferedReader的readLine读取数据的时候一定要记得在对应的输出流里面一定要写入换行符(
			 * 流结束之后会自动标记为结束,readLine可以识别),写入换行符之后一定记得如果输出流不是马上关闭的情况下记得flush一下,
			 * 这样数据才会真正的从缓冲区里面写入。
			 */
			BufferedReader br = new BufferedReader(
					new InputStreamReader(socket.getInputStream(), "UTF-8"));
			StringBuilder sb = new StringBuilder();
			String temp;
			int index;
			while ((temp = br.readLine()) != null) {
				if ((index = temp.indexOf("eof")) != -1) { // 遇到eof时就结束接收
					sb.append(temp.substring(0, index));
					break;
				}
				sb.append(temp);
			}
			System.out.println("Form Cliect[port:" + socket.getPort()
					+ "] 消息内容:" + sb.toString());

			// 回应一下客户端
			Writer writer = new OutputStreamWriter(socket.getOutputStream(),
					"UTF-8");
			writer.write(String.format("Hi,%d.天朗气清,惠风和畅!", socket.getPort()));
			writer.flush();
			writer.close();
			System.out.println(
					"To Cliect[port:" + socket.getPort() + "] 回复客户端的消息发送成功");

			br.close();
			socket.close();
		}

	}

}
 
 
 

  客户端代码

<pre name="code" class="java">import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;

/**
 * Socket客户端<br>
 * 功能说明:
 *
 * @author 大智若愚的小懂
 * @Date 2016年8月30日
 * @version 1.0
 */
public class Client {

	/**
	 * 入口
	 * @param args
	 */
	public static void main(String[] args) {
        // 开启三个客户端,一个线程代表一个客户端
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        TestClient client = TestClientFactory.createClient();
                        client.send(String.format("Hello,Server!I'm %d.这周末天气如何。", client.client.getLocalPort()));
                        client.receive();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    /**
     * 生产测试客户端的工厂
     */
    static class TestClientFactory {

        public static TestClient createClient() throws Exception {
            return new TestClient("127.0.0.1", 8899);
        }

    }

    /**
     * 测试客户端
     */
    static class TestClient {

        /**
         * 构造函数
         * @param host 要连接的服务端IP地址
         * @param port 要连接的服务端对应的监听端口
         * @throws Exception
         */
        public TestClient(String host, int port) throws Exception {
            // 与服务端建立连接
            this.client = new Socket(host, port);
            System.out.println("Cliect[port:" + client.getLocalPort() + "] 与服务端建立连接...");
        }

        private Socket client;

        private Writer writer;

        /**
         * 发送消息
         * @param msg
         * @throws Exception
         */
        public void send(String msg) throws Exception {
            // 建立连接后就可以往服务端写数据了
            if(writer == null) {
                writer = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
            }
            writer.write(msg);
            writer.write("eof\n");
            writer.flush();// 写完后要记得flush
            System.out.println("Cliect[port:" + client.getLocalPort() + "] 消息发送成功");
        }

        /**
         * 接收消息
         * @throws Exception
         */
        public void receive() throws Exception {
            // 写完以后进行读操作
            Reader reader = new InputStreamReader(client.getInputStream(), "UTF-8");
            // 设置接收数据超时间为10秒
            client.setSoTimeout(10*1000);
            char[] chars = new char[64];
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = reader.read(chars)) != -1) {
                sb.append(new String(chars, 0, len));
            }
            System.out.println("Cliect[port:" + client.getLocalPort() + "] 消息收到了,内容:" + sb.toString());
            reader.close();

            // 关闭连接
            writer.close();
            client.close();
        }

    }

}


 


接下来模拟一下:

1.首先运行服务端


2.接着运行客户端(开三个客户端请求)

  为了演示有所区分,服务端使用的是Eclipse工具,客户端使用的是IntelliJ IDEA工具。这时可以看到客户端在控制台打印出来的消息


    一个Port端口号代表一个客户端,回过来看下服务端在控制台打印出来的消息



  • 20
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值