热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Java编程Socket实现多个客户端连接同一个服务端代码

这篇文章主要介绍了Java编程Socket实现多个客户端连接同一个服务端代码,具有一定参考价值,需要的朋友可以了解下。

Java Socket(套接字)通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

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

服务端代码

/**
 * Socket服务端
 * 功能说明:
 * 
 */
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();
		}
	}
}

客户端代码

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
/** * Socket客户端
* 功能说明: * * @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端口号代表一个客户端,回过来看下服务端在控制台打印出来的消息

总结

以上就是本文关于Java编程Socket实现多个客户端连接同一个服务端代码的全部内容,希望对大家有所帮助。有问题可以留言,小编会及时回复大家的。


推荐阅读
  • 在使用Eclipse进行调试时,如果遇到未解析的断点(unresolved breakpoint)并显示“未加载符号表,请使用‘file’命令加载目标文件以进行调试”的错误提示,这通常是因为调试器未能正确加载符号表。解决此问题的方法是通过GDB的`file`命令手动加载目标文件,以便调试器能够识别和解析断点。具体操作为在GDB命令行中输入 `(gdb) file `。这一步骤确保了调试环境能够正确访问和解析程序中的符号信息,从而实现有效的调试。 ... [详细]
  • 本文对SQL Server系统进行了基本概述,并深入解析了其核心功能。SQL Server不仅提供了强大的数据存储和管理能力,还支持复杂的查询操作和事务处理。通过MyEclipse、SQL Server和Tomcat的集成开发环境,可以高效地构建银行转账系统。在实现过程中,需要确保表单参数与后台代码中的属性值一致,同时在Servlet中处理用户登录验证,以确保系统的安全性和可靠性。 ... [详细]
  • 在Java项目中,当两个文件进行互相调用时出现了函数错误。具体问题出现在 `MainFrame.java` 文件中,该文件位于 `cn.javass.bookmgr` 包下,并且导入了 `java.awt.BorderLayout` 和 `java.awt.Event` 等相关类。为了确保项目的正常运行,请求提供专业的解决方案,以解决函数调用中的错误。建议从类路径、依赖关系和方法签名等方面入手,进行全面排查和调试。 ... [详细]
  • 如何在Eclipse中配置不同文件类型的默认打开方式
    在Eclipse中配置不同文件类型的默认打开方式是一项常见的需求。本文将指导您如何轻松地修改Eclipse中各种文件类型的默认打开方式。具体步骤如下:首先,启动Eclipse,然后依次点击【Window】--【Preferences】进入设置界面。接下来,您可以根据需要选择相应的文件类型,并指定其默认打开的编辑器或工具。通过这些设置,您可以显著提升开发效率和工作便捷性。 ... [详细]
  • 在开发过程中,我最初也依赖于功能全面但操作繁琐的集成开发环境(IDE),如Borland Delphi 和 Microsoft Visual Studio。然而,随着对高效开发的追求,我逐渐转向了更加轻量级和灵活的工具组合。通过 CLIfe,我构建了一个高度定制化的开发环境,不仅提高了代码编写效率,还简化了项目管理流程。这一配置结合了多种强大的命令行工具和插件,使我在日常开发中能够更加得心应手。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
  • Java测试服务器调试指南详细介绍了如何进行远程调试,并深入解析了Java Xdebug参数的使用方法。本文首先概述了Java内置的调试功能,重点介绍了JDB这一类似于GDB的强大调试工具。通过实例演示,读者可以掌握在测试环境中高效调试Java应用程序的技巧,包括配置远程调试环境和优化调试参数,以提高开发效率和代码质量。 ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • 基于Java和SSM框架的志愿者管理平台源代码分析与实现
    本研究针对基于Java和SSM框架的志愿者管理平台进行了详细的源代码分析与实现。该平台属于Java Web项目,采用Java EE技术栈,并结合了Spring、Spring MVC和MyBatis三大核心框架(非开源)。项目名称为“基于SSM的志愿者管理系统”,旨在提升志愿者管理的效率和规范性。通过对系统架构、模块设计及关键代码的深入解析,本文为开发者提供了全面的技术参考和实践指导。 ... [详细]
  • 动态壁纸 LiveWallPaper:让您的桌面栩栩如生(第二篇)
    在本文中,我们将继续探讨如何开发动态壁纸 LiveWallPaper,使您的桌面更加生动有趣。作为 2010 年 Google 暑期大学生博客分享大赛 Android 篇的一部分,我们将详细介绍 Ed Burnette 的《Hello, Android》第三版中的相关内容,并分享一些实用的开发技巧和经验。通过本篇文章,您将了解到如何利用 Android SDK 创建引人入胜的动态壁纸,提升用户体验。 ... [详细]
  • PHP与MySQL的Web应用开发技术深入解析
    PHP与MySQL的Web应用开发技术深入解析 ... [详细]
  • 在Eclipse中批量转换Java源代码文件的编码格式从GBK到UTF-8是一项常见的需求。通过编写简单的Java代码,可以高效地实现这一任务。该方法不仅适用于Java文件,还可以用于其他类型的文本文件编码转换。具体实现可以通过导入`java.io.File`类来操作文件系统,从而完成批量转换。此外,建议在转换过程中添加异常处理机制,以确保代码的健壮性和可靠性。 ... [详细]
  • 在Java编程中,`super`关键字主要用于子类继承父类的场景下,当需要在子类的方法中调用父类的方法或访问父类的变量时。需要注意的是,在子类的`main`方法中,由于其静态特性,无法使用`super`或`this`关键字。此外,`super`还可以用于子类构造器中调用父类的构造器,以确保对象的正确初始化。 ... [详细]
  • 基于Java的微信小程序:Spring Boot驱动的中小学家校互动与电子作业管理平台
    基于Java的微信小程序,采用Spring Boot作为后端框架,构建了一个高效的中小学家校互动与电子作业管理平台。前端使用了uni-app框架,确保跨平台兼容性。该平台集成了家校沟通、作业发布与管理、学生成绩查询等功能,旨在提升教育管理效率和家长参与度。后端开发环境配置完善,采用Spring Boot、MyBatis等技术栈,确保系统的稳定性和扩展性。 ... [详细]
  • JBPM 6.5 环境配置深入解析(下篇)
    本文深入探讨了JBPM 6.5 的环境配置细节,从零开始详细介绍了下载、解压后的文件结构,并结合实际操作步骤,为初学者提供了全面的配置指南。通过具体的示例和详细的解释,帮助读者快速掌握 JBPM 6.5 的安装与配置过程。 ... [详细]
author-avatar
AD社团
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有