实现回显服务器(Echo)基于Tcp
目录
一.TCP与UDP二者的区别
TCP实现客户端(不用记录服务器IP和服务器端口号)
UDP实现客户端(必须记录服务器IP和服务器端口号)
二 .实现回显服务器(基于TCP)必须要知道的API
1.ServerSocket
a.SeverSocket构造方法
b.ServerSocket方法
2.Socket
a.Socket构造方法
b.Socket方法
三.实现服务器端的主要思路
思路如下
思路代码如下
给出完整的服务器代码
解释部分重要代码细节(重点掌握)
在idea上设置一个服务器怎么为多个客户端提供服务的设置方法
四.实现客户端的主要思路
思路如下
思路代码如下
给出完整客户端的代码
解释部分重要代码细节(重点掌握)
编辑
代码运行结果如下(一个服务器给两个客户端提供服务)
总结要掌握的点
1.Socket的api
2.实现回显服务器(基于TCP)的点
一.TCP与UDP二者的区别
重点关注有连接部分,由于TCP协议保存了对端的信息,则实现客户端部分的代码时,就不需要记录服务器的IP和服务器的端口号了,与基于UDP去实现客户端代码时,做区分。
TCP实现客户端(不用记录服务器IP和服务器端口号)
public TcpEchoServer(int port) throws IOException {serverSocket=new ServerSocket(port);}
UDP实现客户端(必须记录服务器IP和服务器端口号)
private String ServerIp;private int ServerPort;//服务器的ip与端口号public UdpEchoClient(String ServerIp,int ServerPort) throws SocketException {this.ServerIp=ServerIp;this.ServerPort=ServerPort;//客户端这里的端口号等到操作系统随机分配socket=new DatagramSocket();}
二 .实现回显服务器(基于TCP)必须要知道的API
1.ServerSocket
ServerSocket是创建TCP服务端Socket的API。
a.SeverSocket构造方法
方法签名 | 方法说明 |
ServerSocket(int port) | 创建一个服务端流套接字Socket,并绑定到指定端口 |
b.ServerSocket方法
方法签名 | 方法说明 |
Socket accept() | 开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待 |
void close() | 关闭次套接字 |
2.Socket
Socket是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端的Socket还是服务端的Socket,都是双方建立连接以后,用来存对方信息,还能借助它跟对方收发数据的东西。
如下所示(服务端中接收到客户端建立连接(accept方法)的请求)
Socket clientSocket=serverSocket.accept();
a.Socket构造方法
方法签名 | 方法说明 |
Socket(String host,int port) | 创建一个客户端流套接字Socket,并于对应IP的主机上,对应端口的进程建立连接 |
b.Socket方法
方法签名 | 方法说明 |
InetAddress getInetAddress() | 返回套接字所连接的地址 |
InputStream getInputStream() | 返回此套接字的输入流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
三.实现服务器端的主要思路
思路如下
1.读取请求
2.计算请求
3.返回响应
4.记录服务器日志
思路代码如下
while(true){if(!scanner.hasNext()){System.out.printf("客户端已经下线,%s,%d\n",clientSocket.getInetAddress(),clientSocket.getPort());break;}//1.读取请求String resquest=scanner.next();//2.计算请求,给出响应String response=process(resquest);//3.返回响应printWriter.println(response);//记得刷新缓冲区,使得数据可以及时从缓冲区中输出printWriter.flush();//4.打印日志System.out.printf("%s,%d,%s,%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),resquest,response);}
给出完整的服务器代码
package Internet;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {ServerSocket serverSocket=null;public TcpEchoServer(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {System.out.println("启动服务");ExecutorService executorService= Executors.newCachedThreadPool();//只有在方法内部才可以写whilewhile(true){Socket clientSocket=serverSocket.accept();executorService.submit(()->{try {processconnetion(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}});}}private void processconnetion(Socket clientSocket) throws IOException {System.out.printf("客户端已上线,%s,%d\n",clientSocket.getInetAddress(),clientSocket.getPort());try(InputStream inputStream=clientSocket.getInputStream();OutputStream outputStream=clientSocket.getOutputStream()){//包装一下,为了方便输入与输出Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);while(true){if(!scanner.hasNext()){System.out.printf("客户端已经下线,%s,%d\n",clientSocket.getInetAddress(),clientSocket.getPort());break;}//1.读取请求String resquest=scanner.next();//2.计算请求,给出响应String response=process(resquest);//3.返回响应printWriter.println(response);//记得刷新缓冲区,使得数据可以及时从缓冲区中输出printWriter.flush();//4.打印日志System.out.printf("%s,%d,%s,%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),resquest,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {clientSocket.close();}}private String process(String resquest) {return resquest;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer=new TcpEchoServer(9090);tcpEchoServer.start();}
}
解释部分重要代码细节(重点掌握)
在idea上设置一个服务器怎么为多个客户端提供服务的设置方法
四.实现客户端的主要思路
思路如下
1.发送请求
2.接收响应
3.输出结果
思路代码如下
public void start() throws IOException {System.out.println("请输入请求");Scanner scanner=new Scanner(System.in);try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while(true){Scanner scanner1=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);String resquest=scanner.next();//1.发送请求printWriter.println(resquest);printWriter.flush();//2.接收响应String response=scanner1.next();//3.输出结果System.out.println(response);}//包装一下,为了操作方便}
给出完整客户端的代码
package Internet;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket=null;public TcpEchoClient(String serverIp,int serverPort) throws IOException {socket=new Socket(serverIp,serverPort);}public void start() throws IOException {System.out.println("请输入请求");Scanner scanner=new Scanner(System.in);try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while(true){Scanner scanner1=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);String resquest=scanner.next();//1.发送请求printWriter.println(resquest);printWriter.flush();//2.接收响应String response=scanner1.next();//3.输出结果System.out.println(response);}//包装一下,为了操作方便}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);tcpEchoClient.start();}
}
解释部分重要代码细节(重点掌握)
代码运行结果如下(一个服务器给两个客户端提供服务)
总结要掌握的点
1.Socket的api
UDP | DatagramSocket | DatagramPacket |
Tcp | ServerSocket | Socket |
2.实现回显服务器(基于TCP)的点
1.读写数据通过Socket,通过Socket内置的InputStream和OutputStream
2.在编写客户端服务器的时候,是需要约定请求/响应之间的分割符的(换行符)
3.服务器这边的accept得到的socket对象,要记得即使关闭
4.要处理多个客户端,需要搭配线程池/多线程