Java使用多线程实现Socket多客户端的通信
要想详细了解socket,大家请自行百度,我这里只简单介绍。
在网络中,我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。而socket编程就是为了完成两个唯一进程之间的通信(一个是客户端,一个是服务器端),其中用到的协议是TCP/UDP协议,它们都属于传输层的协议。
TCP是基于连接的协议,在收发数据前,需要建立可靠的连接,也就是所谓的三次握手。使用TCP协议时,数据会准确到达,但是效率较低。
UDP是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去。使用UDP协议时,传输效率高,但是不能保证数据准确到达,视频聊天,语音聊天时就用的UDP协议。
以使用TCP协议通讯的socket为例,其交互流程大概是这样子的:
服务器端 客户端
创建服务器端的socket 创建客户端的socket
绑定端口号 连接服务器端的端口
监听端口 向服务器端发送数据
接收客户端的连接请求 关闭socket
读取客户端发送数据
关闭socket
下面贴上代码:
服务器端:
package SocketStudy; import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket; public class SocketServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(10068);//创建绑定到特定端口的服务器Socket。
Socket socket = null;//需要接收的客户端Socket
int count = 0;//记录客户端数量
System.out.println("服务器启动");
//定义一个死循环,不停的接收客户端连接
while (true) {
socket = serverSocket.accept();//侦听并接受到此套接字的连接
InetAddress inetAddress=socket.getInetAddress();//获取客户端的连接
ServerThread thread=new ServerThread(socket,inetAddress);//自己创建的线程类
thread.start();//启动线程
count++;//如果正确建立连接
System.out.println("客户端数量:" + count);//打印客户端数量
}
} catch (IOException e) {
e.printStackTrace();
} }
}
自定义线程类:
package SocketStudy; import java.io.*;
import java.net.InetAddress;
import java.net.Socket; public class ServerThread extends Thread {
Socket socket = null;
InetAddress inetAddress=null;//接收客户端的连接 public ServerThread(Socket socket,InetAddress inetAddress) {
this.socket = socket;
this.inetAddress=inetAddress;
} @Override
public void run() {
InputStream inputStream = null;//字节输入流
InputStreamReader inputStreamReader = null;//将一个字节流中的字节解码成字符
BufferedReader bufferedReader = null;//为输入流添加缓冲
OutputStream outputStream = null;//字节输出流
OutputStreamWriter writer = null;//将写入的字符编码成字节后写入一个字节流
try {
inputStream = socket.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String info = null;//临时 //循环读取客户端信息
while ((info = bufferedReader.readLine()) != null) {
//获取客户端的ip地址及发送数据
System.out.println("服务器端接收:"+"{'from_client':'"+socket.getInetAddress().getHostAddress()+"','data':'"+info+"'}");
} socket.shutdownInput();//关闭输入流 //响应客户端请求
outputStream = socket.getOutputStream();
writer = new OutputStreamWriter(outputStream, "UTF-8");
writer.write("{'to_client':'"+inetAddress.getHostAddress()+"','data':'我是服务器数据'}");
writer.flush();//清空缓冲区数据
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
if (writer != null) {
writer.close();
}
if (outputStream != null) {
outputStream.close();
}
if (bufferedReader != null) {
bufferedReader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} }
}
客户端:
package SocketStudy; import java.io.*;
import java.net.Socket;
import java.util.Scanner; public class SocketClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("服务器的ip", 10068);
OutputStream outputStream = socket.getOutputStream();//得到一个输出流,用于向服务器发送数据
OutputStreamWriter writer=new OutputStreamWriter(outputStream,"UTF-8");//将写入的字符编码成字节后写入一个字节流
System.out.println("请输入数据:");
Scanner sc = new Scanner(System.in);
String data = sc.nextLine();
writer.write(data);
writer.flush();//刷新缓冲
socket.shutdownOutput();//只关闭输出流而不关闭连接
//获取服务器端的响应数据 InputStream inputStream = socket.getInputStream();//得到一个输入流,用于接收服务器响应的数据
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");//将一个字节流中的字节解码成字符
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);//为输入流添加缓冲
String info = null; System.out.println("客户端IP地址:"+socket.getInetAddress().getHostAddress());
//输出服务器端响应数据
while ((info = bufferedReader.readLine()) != null) {
System.out.println("客户端接收:" + info);
}
//关闭资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
writer.close();
outputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果(先运行服务器端,再运行客户端):
服务器:

客户端:

回车之后
客户端:

服务器端:

在cmd下运行(先编译再运行生成的.class文件,如果有中文,需要加encoding参数,当类中有导入自己创建的类时,需要切换到能包含该类的文件夹下执行命令,否则会报错)

此时的服务器端:

Java使用多线程实现Socket多客户端的通信的更多相关文章
- 《Unity 3D游戏客户端基础框架》多线程异步 Socket 框架构建
引言: 之前写过一个 demo 案例大致讲解了 Socket 通信的过程,并和自建的服务器完成连接和简单的数据通信,详细的内容可以查看 Unity3D -- Socket通信(C#).但是在实际项目应 ...
- 利用多线程使socket服务端可以与多个客户端同时通讯
利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...
- 编写Java程序,使用 Socket类模拟用户加入 QQ 群时,QQ 小冰发送欢迎消息的场景(用户充当客户端,QQ 小冰充当服务端)
查看本章节 查看作业目录 需求说明: 小冰是微软公司研发的人工智能机器人,被腾讯公司加入 QQ 群后,立即受到千万网友的喜爱.现在使用 Socket类模拟用户加入 QQ 群时,QQ 小冰发送欢迎消息的 ...
- 【关于java多线程和socket通信的一些记录】---高并发/高负载/高可用/重入锁
多线程:提高cpu的使用效率,多线程是指在同一程序中有多个顺序流在执行. 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线 ...
- Python拾忆--多线程的socket服务器
阳光明媚的午后,想想最近要开始从写Java到写Python了,就随手打开电脑来体验一下Python与Java之间的不同吧~ 记得我还在上大二的时候,那个时候才开始学Java,最感兴趣的就是Java书最 ...
- 8.多线程和Socket通信
一.多线程 1.进程的概念: 进程就是应用程序的执行实例,有独立的内存空间和系统资源.当一个应用程序没有执行的时候,它就不是一个进程. 2.进行的特征: (1)动态性:动态产生动态消亡. (2)并 ...
- 多线程服务端与客户端通信(IO是阻塞的)_02
下面是多线程的;每次服务端接受请求,会创建一个线程专门处理这个请求: 虽然是多线程的,但还是阻塞,相当于单线程处理模式 public class TimeServer { public static ...
- java基础-多线程应用案例展示
java基础-多线程应用案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.两只熊,100只蜜蜂,蜜蜂每次生产的蜂蜜量是1,罐子的容量是30,熊在罐子的蜂蜜量达到20的时候 ...
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
随机推荐
- java indexOf 和 split的用法
1.java 的 indexOf 方法 ,如果存在 则 指定的字符串的开始位置,如果不存在 则返回-1: 2.java 的 split的方法:将一个字符串分割为子字符串,然后将结果作为字符串数组返回. ...
- Django 简单教程(入门级)
一.Django简介 1. web框架介绍 具体介绍Django之前,必须先介绍WEB框架等概念. web框架: 别人已经设定好的一个web网站模板,你学习它的规则,然后“填空”或“修改”成你自己需要 ...
- CentOS随笔 - 修改CentOS7的IP
前言 转帖请注明出处: http://www.cnblogs.com/Troy-Lv5/ 在使用CentOS时经常我们需要固定一个IP, 因为服务器嘛,不固定IP. 难道每次都要配置开发环境的地址.? ...
- [翻译] LTInfiniteScrollView
LTInfiniteScrollView 效果: Usage - 使用 Create the scroll view by: 通过以下方式来创建出scroll view self.scrollView ...
- css动画 文字闪烁效果
/*定义页面基础CSS*/ body{ font-family: 'microsoft yahei',Arial,sans-serif; color: #EFEFEF; background: #22 ...
- 音乐MP4网站 车辆工程 冯大昕
- Mysql常用的锁机制
一.引言 ...
- MapReduce Design Patterns(chapter 1)(一)
Chapter 1.Design Patterns and MapReduce MapReduce 是一种运行于成百上千台机器上的处理数据的框架,目前被google,Hadoop等多家公司或社区广泛使 ...
- openresty及lua的随机函数
我们都知道,所谓的随机都是伪随机,随机的结果是由随机算法和随机种子决定的. 所以,当我们没有初始化的时候,如果直接使用math.random(),那么出来的值肯定是每次都一样,因为种子等于0. 因此, ...
- Linq to Entities,ADO.NET Entity Framework 模型优先
一.概念: Database First(数据库优先):存在的DB------------->生成Data Model .edmx文件 Model First(模型优先):Data Model ...