1基于tcp协议的编程模型
案例:使用多线程方法,实现服务器接收客户端消息。
1.1 服务器类
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
public class TcpServerTest {
public static void main(String[] args) {
ServerSocket ss = null;
Socket socket = null;
try {
// 创建ServerSocket类型的对象并提供端口号
ss = new ServerSocket(8888);
System.out.println("等待客户端连接..");
while(true){
// 当没有客户端连接时,则服务器阻塞在accept方法的调用这里
socket = ss.accept();
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yy-MM-dd hh:mm:ss");
String dateTime = dtf.format(ldt);
System.out.println(dateTime + " 客户端 " + socket.getInetAddress() + " " +
socket.getPort() + " 连接成功 !");
// 每当有一个客户端连接成功,则需要启动一个新的线程为之服务
new TcpServeThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(null != ss)
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.2 客户端类
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class TcpClientTest {
public static void main(String[] args) {
Socket socket = null;
PrintStream ps = null;
Scanner s = new Scanner(System.in);
try {
socket = new Socket("127.0.0.1",8888);
System.out.println("连接到服务器..");
System.out.println("输入要发送的内容:");
while(true){
//读取键盘输入
String inputStr = s.nextLine();
// 由客户端向服务器发送消息
Thread.sleep(1000);
ps = new PrintStream(socket.getOutputStream());
ps.println(inputStr);
System.out.println("发送成功!");
if("Bye".equalsIgnoreCase(inputStr)){
System.out.println("客户端即将下线..");
break;
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if(null != ps)
ps.close();
if(null != socket) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.3 自定义线程类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TcpServeThread extends Thread{
private Socket socket = null;
private BufferedReader br = null;
public TcpServeThread(Socket socket) {
this.socket = socket;
}
@Override
public void run(){
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true){
String content = br.readLine();
// 获取当前时间
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yy-MM-dd hh:mm:ss");
String dateTime = dtf.format(ldt);
System.out.println("客户端 " + socket.getInetAddress() + " " + socket.getPort() +
" " + dateTime + ": " + content);
if("Bye".equalsIgnoreCase(content)){
System.out.println("客户端下线!");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != socket) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2基于udp协议的编程模型
案例:使用Udp协议实现接收方和发送方互传信息。
2.1 接收方类
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class UdpReceiveTest {
public static void main(String[] args) {
DatagramSocket ds = null;
DatagramPacket dp = null;
try {
// 创建DatagramSocket类型的对象
ds = new DatagramSocket(8888);
System.out.println("服务器上线..");
System.out.println("当前主机的通讯地址地址为: " + InetAddress.getLocalHost());
System.out.println("回环地址地址为: " + InetAddress.getLoopbackAddress());
while(true){
byte[] receiveStr = new byte[40];
// 创建DataPocket类型的对象
dp = new DatagramPacket(receiveStr, receiveStr.length);
System.out.println("等待客户端发送数据..");
// 接受数据
ds.receive(dp);
// sleep 2s
Thread.sleep(3500);
String str = new String(receiveStr, 0, dp.getLength(),StandardCharsets.UTF_8);
System.out.println("发送方方的ip地址为:" + dp.getAddress() + " 发送方的端口号为:" + dp.getPort());
System.out.println("客户端数据接受完毕..");
System.out.println("接受到的数据为:" + str);
//向发送方回发消息: I received !
System.out.println("开始向发送方回复消息..");
byte[] mesReply = "I received !".getBytes(StandardCharsets.UTF_8);
dp = new DatagramPacket(mesReply, mesReply.length, dp.getAddress(), dp.getPort());
ds.send(dp);
System.out.println("回复消息结束");
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if(null != ds){
ds.close();
}
}
}
}
2.2 发送方类
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
public class UdpSendTest {
public static void main(String[] args) {
DatagramSocket ds = null;
try {
// 要发送的内容
// byte[] serveInetAddress = new byte[]{[192, 168, 14, 209]};
// String message = "My dear son. Your father love you.";
String message = "0Java是世界上最好的语言";
byte[] mesByte;
mesByte = message.getBytes(StandardCharsets.UTF_8);
// 创建DatagramSocket对象
ds = new DatagramSocket();
// 创建DatagramPocket对象
DatagramPacket dp = new DatagramPacket(mesByte, mesByte.length, InetAddress.getLocalHost(), 8888);
System.out.println("开始以Udp的形式向服务器发送信息..");
ds.send(dp);
System.out.println("信息发送成功!");
// 接收方返回的消息
mesByte = new byte[40];
DatagramPacket dp2 = new DatagramPacket(mesByte, mesByte.length);
ds.receive(dp2);
System.out.println("接收方返回的消息为:" + new String(mesByte, 0, dp2.getLength(), StandardCharsets.UTF_8));
System.out.println("发送方地址:" + dp2.getAddress() + " 发送方端口号" + dp2.getPort());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(null != ds){
ds.close();
}
}
}
}