Java多线程TCP客户端与服务器间使用Socket通信
Socket是一个有效的网络通信的工具,下面这个简单例子给大家演示一下如何使用Socket来做服务器与客户端之间的通信 客户端代码
/**
* @author Jian
* 客户端
*/
public class Client {
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口,本机也可以为localhost
Socket socket= new Socket("127.0.0.1", 1344);
//2.获取输出流,向服务器端发送登录信息
OutputStream os = socket.getOutputStream();
//字节输出流
*//**
*可以装饰为打印流,也可以采用下装饰为字符输出流,使用缓冲来写入
*PrintWriter pw = new PrintWriter(os);
//输出流包装为打印流
*//*
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter pw = new BufferedWriter(osw);
pw.write("用户名:admin;
密码:123");
pw.flush();
//调用flush()刷新缓存
//关闭输出流
socket.shutdownOutput();
//3.获取输入流,读取服务器端相应信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
//字节流转换为字符流
BufferedReader br = new BufferedReader(isr);
//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取服务器端响应信息
System.out.println("服务器端信息:"+info);
}
//4.关闭相关资源
br.close();
isr.close();
is.close();
pw.close();
osw.close();
os.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
服务器端代码
/**
* @author Jian
* 基于TCP协议的Socket通信,实现用户登录
* 服务器端
*/
public class Server {
/*public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(1344);
//2.调用accept()方法,等待客户端的连接
System.out.println("-----服务器即将启动,等待客户端连接");
Socket socket = serverSocket.accept();
//阻塞式
//3.获取输入流,并读取客户端信息
InputStream is = socket.getInputStream();
//字节输入流
InputStreamReader isr = new InputStreamReader(is);
//字节流转换为字符流
BufferedReader br = new BufferedReader(isr);
//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取
System.out.println("服务器收到的客户端数据"+info);
}
//socket.shutdownInput();
//关闭输入流
//4.获取输出流,响应客户端的请求
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("Welcome!");
pw.flush();
//刷新缓存
//5.关闭相关资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
在客户端的代码中,发送完数据后需要调用shutdownOutput()来告诉服务器端已经发送完毕,这样会使得接下来再利用输出流来向服务器发送信息,所以我们可以将代码稍加修改 服务器端
DataInputStream dis = new DataInputStream(is);
int flag = 0;
while(true){//循环读取
flag = br.read();
System.out.println(flag);
if(flag==1){
String data = https://www.it610.com/article/dis.readUTF();
System.out.println(data);
}
break;
}
客户端
DataOutputStream dos = new DataOutputStream(os);
pw.write(1);
pw.flush();
dos.writeUTF(("用户名:admin;
密码:123"));
dos.flush();
//调用flush()刷新缓存
//关闭输出流
//socket.shutdownOutput();
这里我们可以先约定好通信协议,传数字代表的含义,然后可以在服务器端的监听中调用别的方法,使用DataInputStream的readUTF()方法可以读取整段文字,你可以自行设计方法,来避免shutdownIn/Output()后造成无法读写的问题。 尝试一下多线程下的Socket通信
【Java多线程TCP客户端与服务器间使用Socket通信】客户端没有什么变化,只要让Server保持死循环监听,每有一个客户端连接进来,就开启一个线程,并在这个线程里与客户端进行通信,具体代码如下:服务器端
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(1344);
//2.调用accept()方法,等待客户端的连接
System.out.println("-----服务器即将启动,等待客户端连接");
Socket socket = null;
//記錄客戶端數量
int count = 0;
while(true){
socket = serverSocket.accept();
//阻塞式
//創建一個新的線程
ServerThread serverThread = new ServerThread(socket);
serverThread.start();
count++;
System.out.println("客戶端數量:"+count);
InetAddress address = socket.getInetAddress();
System.out.println("當前客戶端的IP:"+address.getHostAddress());
}
//serverSocket.close();
线程类
/**
* @author Jian
* 服务器端线程处理类
*/
public class ServerThread extends Thread{
//和本线程相关的Socket
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
//线程的操作,响应客户端请求
public void run(){
InputStreamReader isr=null;
InputStream is=null;
BufferedReader br=null;
OutputStream os=null;
PrintWriter pw=null;
//3.获取输入流,并读取客户端信息
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
//字节流转换为字符流
br = new BufferedReader(isr);
//为输入流添加缓冲
String info = null;
while((info=br.readLine())!=null){//循环读取
System.out.println("服务器收到的客户端数据"+info);
}
socket.shutdownInput();
//关闭输入流
//4.获取输出流,响应客户端的请求
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("Welcome!");
pw.flush();
//刷新缓存} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//5.关闭相关资源
try {
if(pw!=null)
pw.close();
if(os!=null)
os.close();
if(br!=null)
br.close();
if(isr!=null)
isr.close();
if(is!=null)
is.close();
if(socket!=null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}
}
这里列举的只是基本的用法,希望能对你有所帮助,大家还需要多加练习,加油!
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 爱就是希望你好好活着
- 昨夜小楼听风
- 知识
- 死结。
- 我从来不做坏事
- 烦恼和幸福
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- 事件代理