网络编程Socket
DatagramSocket——创建一个UDP版本的socket对象
- receive: 接收数据
- send: 发送数据
- close: 释放资源
DatagramPacket——表示一个UDP数据报
使用
服务器
public class UdpEchoServer {
//多个进程不能绑定一个端口
//一个进程可以绑定多个端口
private DatagramSocket socket = null;
public UdpEchoServer(int port) throws SocketException {
socket = new DatagramSocket(port); //port:端口号
}
public void start() throws IOException {
System.out.println("启动服务器");
while(true){
DatagramPacket packet = new DatagramPacket(new byte[1024] , 1024); //用于接受
socket.receive(packet);
String request = new String(packet.getData() ,0, packet.getLength(),"UTF-8");
String response = process(request);
DatagramPacket responsePacket = new DatagramPacket(response.getBytes() ,
response.getBytes().length,
packet.getSocketAddress()); //用于发送
socket.send(responsePacket);
System.out.printf("[%s:%d] req: %s,resp:%s\n" , packet.getAddress().toString() , packet.getPort()
,request , response);
}
}
public String process(String request){
return request;
}
public static void main(String[] args) throws IOException {
UdpEchoServer server = new UdpEchoServer(9090);
server.start();
}
}
客户端
public class UdpEchoClient {
//通常服务器弄端口号的时候是自己定的,客户端的端口号是随机的
private DatagramSocket socket = null;
private String serverIp;
private int port;
public UdpEchoClient(String serverIp , int port) throws SocketException {
socket = new DatagramSocket();
this.serverIp = serverIp;
this.port = port;
}
public void start() throws IOException {
Scanner sc = new Scanner(System.in);
while(true){
String request = sc.next();
DatagramPacket requestPacket = new DatagramPacket(request.getBytes() , request.getBytes().length ,
InetAddress.getByName(serverIp) , port); //用于发送
socket.send(requestPacket);
DatagramPacket responsePacket = new DatagramPacket(new byte[1024] , 1024);
socket.receive(responsePacket);
String response = new String(responsePacket.getData() , 0 , responsePacket.getLength() , "UTF-8");
System.out.printf("req: %s , resp: %s/n" , request , response);
}
}
public static void main(String[] args) throws IOException {
UdpEchoClient client = new UdpEchoClient("127.0.0.1" , 9090);
client.start();
}
}
记住,要先开启服务器,后面开启客户端。
ServerSocket——用于TCP
Socket——用于TCP
先要建立连接才可以用。
使用
服务器
public class TcpEchoServer {
private ServerSocket serverSocket = null;
public TcpEchoServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void start() throws IOException {
System.out.println("服务器开始");
while(true){
Socket clientSocket = serverSocket.accept(); //接听,如果没有客户端来就会阻塞
Thread t = new Thread(()->{ //这个是为了服务器可以接收多个客户端。
processConnection(clientSocket);
});
t.start();
}
}
public void processConnection(Socket clientSocket){
System.out.printf("[%s:%d]" , clientSocket.getInetAddress().toString() , clientSocket.getPort());
try(InputStream inputStream = clientSocket.getInputStream()){
try(OutputStream outputStream = clientSocket.getOutputStream()){
Scanner sc = new Scanner(inputStream);
while(true){
//读取请求
if(!sc.hasNext()){
System.out.printf("[%s:%d]客户端断开连接!" , clientSocket.getInetAddress().toString() , clientSocket.getPort());
break;
}
//根据请求返回响应
String request = sc.next();
String response = process(request);
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(response);
printWriter.flush(); //刷新缓冲区,让客户端能第一时间看到响应
System.out.printf("[%s:%d] req:%s resp:%s\n" , clientSocket.getInetAddress().toString() , clientSocket.getPort()
,request , response);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
clientSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public String process(String request){
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer server = new TcpEchoServer(9090);
server.start();
}
}
客户端
public class TcpEchoClient {
private Socket socket = null;
public TcpEchoClient() throws IOException {
socket = new Socket("127.0.0.1" , 9090); //这边连接的是服务器的IP和端口
}
public void start(){
System.out.println("和服务器连接成功");
Scanner sc = new Scanner(System.in);
try(InputStream inputStream = socket.getInputStream()) {
try(OutputStream outputStream = socket.getOutputStream()){
while(true){
String request = sc.next();
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(request);
printWriter.flush();
Scanner scInput = new Scanner(inputStream);
String response = scInput.next();
System.out.printf("req:%s resp:%s\n" , request , response);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws IOException {
TcpEchoClient client = new TcpEchoClient();
client.start();
}
}
优化,加上线程池
public void start() throws IOException {
System.out.println("服务器开始");
ExecutorService pool = Executors.newCachedThreadPool();
while(true){
Socket clientSocket = serverSocket.accept(); //接听,如果没有客户端来就会阻塞
// Thread t = new Thread(()->{ //这个是为了服务器可以接收多个客户端。
// processConnection(clientSocket);
// });
// t.start();
pool.submit(new Runnable() {
@Override
public void run() {
processConnection(clientSocket);
}
});
}
}
这样提高了效率。