TCP服务器
注意事项:
1.getInetAddress() getPost() :得到对端的ip和端口
getLocalAddress() getLocalPost() :得到本地的ip和端口
2.inputstream进行read操作,就是‘接收’
Outputstream进行write操作,就是‘发送’
发送接收的时候以“字节”为单位进行展开。
3.serverSocket(给服务器使用的,用这个类绑定端口号)
server(既给服务器用,又给客户端用)
4.对于回显服务器来说,响应和请求是一样的
5.!!!为什么clientSocket需要close?
Socket clientSocket=serverSocket.accept();每次执行这个,都会创建新的clientSocket,这个socket最多使用到客户端退出(断开连接),当连接断开clientsocket就失去了作用,如果没有手动close 这个socket就会占据着文件描述符的位置。
总结:
1.next作为读取请求的方式,next 的规则是遇到“空白符”就返回。(服务器这里以\n作为空白符)
2.根据请求计算响应。
3.把响应写回到客户端。
4.打印请求交互的内容
package network;
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;
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){
//通过accept方法,把内核中已经建立好的连接拿到应用程序中
//tcp建立连接的细节都是内核自动完成的,应用程序只要直接拿来用就行
Socket clientSocket=serverSocket.accept();
processConnection(clientSocket);
}
}//通过这个方法,来处理当前的连接
public void processConnection(Socket clientSocket) throws IOException {
System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress(),clientSocket.getPort());
//使用方法,避免后续用完了流对象,忘记关闭
try(InputStream inputStream=clientSocket.getInputStream();
OutputStream outputStream=clientSocket.getOutputStream()){
//使用try()方式,避免后续用完了流对象,忘记关闭
//客户端发来的请求,可能是多条数据,做循环处理
while(true){
Scanner scanner =new Scanner(inputStream);
if(!scanner.hasNext()){
//连接断开,循环结束
System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress(),clientSocket.getPort());
break;
}
// next作为读取请求的方式,next 的规则是遇到“空白符”就返回。(服务器这里以\n作为空白符)
String request=scanner.next();
String response=process(request);
//使用PrintWriter把OutputStream包裹一下,写入到字符串
PrintWriter printWriter=new PrintWriter(outputStream);
printWriter.println(response);
//刷新缓冲区
printWriter.flush();
System.out.printf("[%s:%d] req=%s,resp=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);
}
} catch(IOException e){
e.printStackTrace();
}finally {
clientSocket.close();
}
}
public String process(String request){
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer server=new TcpEchoServer(9090);
server.start();
}}
TCP客户端
1.从控制台读取用户输入的内容
2.把字符串作为请求,发送给服务器
3.从服务器读取响应。
4.把响应显示到界面上
package network;
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的同时,和服务器建立连接,就得告诉socket服务器在哪
//具体建立的细节,内核负责,无需手动创建
socket=new Socket(serverIp,serverPort);
//当我们new对象的时候,操作系统内核,就开始进行三次握手协议,完成建立连接的过程
}
public void start(){
//1.从控制台读取用户输入的内容
//2.把字符串作为请求,发送给服务器
//3.从服务器读取响应。
//4.把响应显示到界面上
Scanner scanner=new Scanner(System.in);
try (InputStream inputStream=socket.getInputStream();
OutputStream outputStream=socket.getOutputStream()){
Scanner scannerNetwork=new Scanner(inputStream);
while(true){
System.out.println("->");
String request=scanner.next();
PrintWriter writer=new PrintWriter(outputStream);
writer.println(request);
writer.flush();
String response=scannerNetwork.next();
System.out.println(response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
TcpEchoClient client=new TcpEchoClient("127.0.0.1",9090);
client.start();
}
}
运行截图:
tcp程序,客户端一启动,立马就会和服务器建立连接。服务器这边感受到(accept方法就会返回,进一步的进入到processConnection中)。服务器停止,客户端立马显示下线