Java编程Socket实现多个客户端连接同一个服务端代码
作者:大智若愚的小懂 发布时间:2023-12-27 05:32:11
标签: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端口号代表一个客户端,回过来看下服务端在控制台打印出来的消息
来源:https://www.2cto.com/kf/201609/543865.html
0
投稿
猜你喜欢
- 先通过idea或者eclipse也或者cmd把后缀java编译成class文件编译好的class文件,找到本地目录,运行cmd输入:jar
- 前言底部Tab已经是一个应用的标配了,因为手机屏幕大小的限制,使得我们必须去最大化的利用可见的空间。当然底部Tab一般为3个左右,最多不会超
- 前言在上一章节Spring和Mybatis整合的原理详解中有写到Spring和MyBatis整合时用到的Bean扫描是Spring本身提供的
- 一、前言null与NULL不都是表示空值吗?这有什么值得深入讨论的的?首先你在编写Java代码时使用过NULL吗?大概用IDE用习惯了,自动
- 数字可以标志货币、百分比、积分和电话号码等,就货币而言,在不同的国家会以不同的格式来定义,本实例将接收用户输入的数字,然后在控制台中输出其货
- 查了下网上的一些资料,感觉比较复杂,这里,我这几使用两种很简单的办法解决了中文乱码问题。Spring版本:3.2.2.RELEASEJack
- 依赖的jar包:spring相关jar包版本:4.3.1.RELEASE<dependency> &l
- Vector的基本介绍1.:Vector类的定义:public class Vector<E> ext
- 本文实例为大家分享了Unity3D实现摄像机镜头移动并限制角度的具体代码,供大家参考,具体内容如下摄像机镜头跟随鼠标移动,并限制上下左右的移
- WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数
- 由于一个项目的需要,我研究了一下android的网络通信方式,大体和java平台的很相似! android平台也提供了很多的AP
- 本文实例为大家分享了Java读取并下载网络文件的具体代码,供大家参考,具体内容如下import java.io.ByteArrayOutpu
- Gradle 属性( Gradle build environment)[详细信息]("https://docs.gradle.o
- 本文所需的数据库初始文件,Hibernate常用操作的完整示例代码(包含所有Hibernate操作所需jar文件)提供下载学习:http:/
- 静态方法和非静态方法的区别:1.静态方法不需要类实例化就可以调用,反之非静态方法需要实例化后才能调用;2.静态方法只能访问静态成员和方法,非
- Java BorderLayout布局管理器的两种排列java中Frame类默认的布局管理器为BorderLayout,其主要是将Frame
- 本文实例讲述了C#实现在图像中绘制文字图形的方法。分享给大家供大家参考。具体实现方法如下:using System;using System
- 关于idea2021最新激活教程,请点击此处,获取最新激活教程还有一种激活方法,点击此处获取吧 !下面看下IDEA 2021.2 启动报错问
- 本文实例讲述了Android SQLite数据库操作方法。分享给大家供大家参考,具体如下:SQLite and AndroidSQLite简
- 前言现在很多应用都会用到地图,但是我们肯定不想自己的app中还要弄个导航神马的,所以第三方的地图也为我们开辟了一条捷径,直接将数据传输到地图