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参数,当类中有导入自己创建的类时,需要切换到能包含该类的文件夹下执行命令,否则会报错)

此时的服务器端:

  

猜你喜欢

转载自www.cnblogs.com/aibaofeng/p/10139005.html