(一)Socket概念:
socket时TCP/IP协议的抽象,是操作系统对外开放的接口 socket起源于unix,京客户端和服务端各自管理一个文件,是其能分别对文件进行读写操作 socket的通信流程:
(二)代码实现:
运行代码时要先运行服务器端,在运行客户端
编写TCP和UDP实现服务端与客户端的通信:
只能固定发送数据
TCP实现:
服务器端实现:
- 创建Socket,并将socket绑定端口
- while循环使得socket一直在等待状态
- 监听端口
- 获取客户端请求信息后,执行相关业务逻辑
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer{
public static void main(String []agrs)throws Exception{
ServerSocket ss=new ServerSocket(65000);
while(true){
Socket socket=ss.accept();
new LengthCalculator(socket).start();
}
}
}
线程运行持续获得客户端的请求后,回送信息:
- 获取socket输入流
- 获取socket输出流
- buff读取输入内容
- 将接受流的byte数组转化为字符串
- 回送客户端字符串长度
- 关闭
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class LengthCalculator extends Thread{
private Socket socket;
public LengthCalculator(Socket socket){
this.socket=socket;
}
public void run(){
try{
OutputStream os=socket.getOutputStream();
InputStream is=socket.getInputStream();
int ch=0;
byte[]buff=new byte[1024];
ch=is.read(buff);
String content=new String(buff,0,ch);
os.write(String.valueOf(content.length()).getBytes());
is.close();
os.close();
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
客户端的实现:
- 创建socket,并指定连接端口
- 获取输出流
- 获取输入流
- 将要传递给server的字符串转换为byte数组
- buff读取输入内容
- ch获取读取长度
- 关闭输入流及socket
import java.io.OutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.net.Socket;
public class TCPClient{
public static void main(String []args)throws Exception{
Socket socket=new Socket(new InetSocketAddress("127.0.0.1",65000);
OutputStream os=socket.getOutputStream();
InputStream is=socket.getInputStream();
os.write(new String("hello world").getBytes());
int ch=0;
byte[]buff=new byte[1024];
ch=is.read(buff);
String connect=new String (buff,0,ch);
System.out.println(connect);
is.close();
os.close();
socket.close();
}
}
UDP实现:
运行代码时要先运行服务器端,在运行客户端 服务器端:
- 服务器端接受客户端发送的数据报
- 监听端口号
- 存储从客户端接收的内容
- 将客户端发送的内容封装进入DatagramPacket中
- 将数据从二进制转化为字符串的形式
- 将要发送的信息转化为二进制
- 服务端发送数据报
- 从DatagramPacket对象中获取到数据的来源地址和端口号
- 发送数据给客户端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPServer{
public static void main(String []args) throws Exception{
DatagramSocket socket=new DatagramSocket(65001);
byte[]buff=new byte[100];
DatagramPacket packet=new DatagramPacket(buff,buff.length);
socket.receive(packet);
byte[]data=packet.getData();
String content=new String(data,0,packet.getLength());
System.out.println(content);
byte[]sendedContent=String.valueOf(content.length()).getBytes();
DatagramPacket packetToClient=new DatagramPacket(sendedContent,sendedContent.length,packet.getAddress(),packet.getPort());
socket.send(packetToClient);
}
}
客户端实现:
- 客户端给服务器端发送数据
- 存储要发送的数据
- 将IP地址封装成InetAddres对象
- 将要发送给服务器端的数据封装为DatagramPacket对象,要写上ip与端口号
- 发送数据给服务器
- 客户端接收服务器的数据
- 创建DatagramPacket对象来存储服务器发送的数据
- 将服务器端发送的数据取出并打印到控制台
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPClient{
public static void main(String[]args)throws Exception{
DatagramSocket socket=new DatagramSocket();
byte[]buf="hello world".getBytes();
InetAddress address=InetAddress.getByName("127.0.0.1");
DatagramPacket packet=new DatagramPacket(buf,buf.length,address,65001);
socket.send(packet);
byte[]data=new byte[100];
DatagramPacket receivedPacket=new DatagramPacket(buf,buf.length);
socket.receive(receivedPacket);
String content=new String(receivedPacket.getData(),0,receivedPacket.getLength());
System.out.println(content);
}
}
(三)升级版
可从键盘输入数据并发送
import java.io.*;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket();
socket.setSoTimeout(3000);
socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 2000), 3000);
System.out.println("已发起服务器连接,并进入后续流程~");
System.out.println("客户端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());
System.out.println("服务器信息:" + socket.getInetAddress() + " P:" + socket.getPort());
try {
todo(socket);
} catch (Exception e) {
System.out.println("异常关闭");
}
socket.close();
System.out.println("客户端已退出~");
}
private static void todo(Socket client) throws IOException {
InputStream in = System.in;
BufferedReader input = new BufferedReader(new InputStreamReader(in));
OutputStream outputStream = client.getOutputStream();
PrintStream socketPrintStream = new PrintStream(outputStream);
InputStream inputStream = client.getInputStream();
BufferedReader socketBufferedReader = new BufferedReader(new InputStreamReader(inputStream));
boolean flag = true;
do {
String str = input.readLine();
socketPrintStream.println(str);
String echo = socketBufferedReader.readLine();
if ("bye".equalsIgnoreCase(echo)) {
flag = false;
}else {
System.out.println(echo);
}
}while (flag);
socketPrintStream.close();
socketBufferedReader.close();
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(2000);
System.out.println("服务器准备就绪~");
System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());
for (; ; ) {
Socket client = server.accept();
ClientHandler clientHandler = new ClientHandler(client);
clientHandler.start();
}
}
private static class ClientHandler extends Thread {
private Socket socket;
private boolean flag = true;
ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
super.run();
System.out.println("新客户端连接:" + socket.getInetAddress() +
" P:" + socket.getPort());
try {
PrintStream socketOutput = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
do {
String str = socketInput.readLine();
if ("bye".equalsIgnoreCase(str)) {
flag = false;
socketOutput.println("bye");
} else {
System.out.println(str);
socketOutput.println("回送:" + str.length());
}
} while (flag);
socketInput.close();
socketOutput.close();
} catch (Exception e) {
System.out.println("连接异常断开");
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("客户端已退出:" + socket.getInetAddress() +
" P:" + socket.getPort());
}
}
}
服务器端运行后如图: 客户端运行后如图: 在客户端输入数据后如图效果 输入bye时退出:
运行代码时要先运行服务器端,在运行客户端
|