多线程处理多请求
采用多线程的方式,实现多客户请求
一个专门负责监听的应用主服务程序
一个专门负责处理请求的线程程序
小练习:多客户端用户登录
需求说明
模拟用户登录的功能
实现客户发送登录用户信息,服务器端显示登录信并响应给客户端登录成功
实现多客户端用户登录
分析
创建服务器端线程类,run()方法中实现对一个请求的响应处理
修改服务器端代码,实现循环监听状态 、
服务器端每监听到一个请求,创建一个处理线程
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户名 */
private String loginName;
/** 用户密码 */
private String pwd;
public User() {
super();
}
public User(String loginName, String pwd) {
super();
this.loginName = loginName;
this.pwd = pwd;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
//-----------------------------------------------------------------
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 建立一个服务器Socket(ServerSocket)指定端口并开始监听
serverSocket = new ServerSocket(8800);
// 监听一直进行中
while (true) {
// 使用accept()方法等待客户发起通信
Socket socket = serverSocket.accept();
LoginThread loginThread = new LoginThread(socket);
loginThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//--------------------------------------------------------------------
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class LoginThread extends Thread {
Socket socket = null;
//每启动一个线程,连接对应的Socket
public LoginThread(Socket socket) {
this.socket = socket;
}
//启动线程,即响应客户请求
public void run() {
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
try {
//打开输入流
is = socket.getInputStream();
//反序列化
ois = new ObjectInputStream(is);
//获取客户端信息,即从输入流读取信息
User user = (User)ois.readObject();
if(user!=null){
System.out.println("我是服务器,客户登录信息为:"+user.getLoginName()+","+user.getPwd());
}
//给客户端一个响应,即向输出流中写入信息
os = socket.getOutputStream();
String reply = "欢迎你,登录成功";
os.write(reply.getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
try {
os.close();
ois.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//----------------------------------------------------------------
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient01 {//其他客户端与一相仿,可自己动手尝试呦
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
ObjectOutputStream oos = null;
InputStream is = null;
BufferedReader br = null;
try {
// 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800
socket = new Socket("localhost", 8800);
// 打开输出流
os = socket.getOutputStream();
// 对象序列化
oos = new ObjectOutputStream(os);
// 发送客户端信息,即向输出流中写入信息
User user = new User("Tom", "123456");
oos.writeObject(user);
socket.shutdownOutput();
// 接收服务器端的响应,即从输入流中读取信息
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String reply;
while ((reply = br.readLine()) != null) {
System.out.println("我是客户端,服务器的响应为:" + reply);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
is.close();
oos.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
基于UDP协议的Socket编程
TCP | UDP | |
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
速度 | 慢 | 快 |
基于UDP协议的Socket网络编程步骤
1.利用 DatagramPacket 对象封装数据包
2.利用 DatagramSocket 发送数据包
3.利用 DatagramSocket 接收数据包
4.利用 DatagramPacket 处理数据包
举栗:模拟客户咨询问题,实现发送方发送咨询问题,接收方接收并显示发送来的咨询问题。
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Send {
public static void main(String[] args) {
DatagramSocket ds = null;
InetAddress ia = null;
String mess = "你好,我想咨询一个问题。";
try {
//获取本地主机地址
ia = InetAddress.getByName("localhost");
//创建DatagramPacket对象,封装数据
DatagramPacket dp = new DatagramPacket(mess.getBytes(), mess.getBytes().length, ia, 8800);
//创建DatagramSocket对象,向服务器发送数据
ds = new DatagramSocket();
ds.send(dp);
//接收服务器端发送的响应信息
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
ds.close();
}
}
}
//------------------------------------------------------------------------------------------
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Receive {
public static void main(String[] args) {
DatagramSocket ds = null;
//创建DatagramPacket对象,用来准备接收数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
try {
//创建DatagramSocket对象,接收数据
ds = new DatagramSocket(8800);
ds.receive(dp);
//显示接收到的信息
String mess = new String(dp.getData(), 0, dp.getLength());
System.out.println(dp.getAddress().getHostAddress()+"说:"+mess);
//向客户端发送响应信息
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
ds.close();
}
}
}