一、TCP的相关IP
1.1 SeverSocket
这是Socket类,对应到网卡,但是这个类只能给服务器使用.
1.2 Socket
对应到网卡,既可以给服务器使用,又可以给客户端使用.
TCP是面向字节流的,传输的基本单位是字节.
TCP是有连接的,和打电话一样,需要客户端拨号,服务器来听.
服务器的内核会配合客户端这边的工作,来完成连接的建立.
这个连接建立的过程,就相当于电话这边在拨号,另外一边就在响铃.
但是需要等待用户点击了接听,才能进行后续通信.
内核建立的连接不是决定性的,还需要用户程序,把这个程序进行 "接听"/ accept 操作,然后才能进行后续的通信.
accept也是一个可能会产生阻塞的操作,如果当前没有客户端连过来,此时accept就会阻塞.
有一个客户端连过来了,accept一次就能返回一次
有若干个客户端连过来了,accept就需要执行多次.
二、实现TCP回显服务器
2.1 服务器代码
private ServerSocket serverSocket = null;
public TcpEchoServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
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() {
try {
processConnection(clientSocket);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
}
private 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()){
while(true){
Scanner scanner = new Scanner(inputStream);
if(!scanner.hasNext()){
System.out.printf("[%s:%d] 客户端下线",clientSocket.getInetAddress(),clientSocket.getPort());
break;
}
String resquest = scanner.next();
String response = process(resquest);
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(response);
printWriter.flush();
System.out.printf("[%s;%d] req: %s,resp: %s\n",clientSocket.getInetAddress(),clientSocket.getPort(),
resquest,response);
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
clientSocket.close();
}
}
public String process(String request){
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer sever = new TcpEchoServer(9090);
sever.start();
}
2.2 客户端代码
private Socket socket = null;
public TcpEchoClient(String severIp,int severPort) throws IOException {
socket = new Socket(severIp,severPort);
}
public void start(){
System.out.println("客户端启动");
try(InputStream inputStream =socket.getInputStream();
OutputStream outputStream = socket.getOutputStream()) {
Scanner scannerConsole = new Scanner(System.in);
Scanner scannerNetwoek = new Scanner(inputStream);
PrintWriter writer = new PrintWriter(outputStream);
while(true){
//1.从控制台读取字符
System.out.println("->");
if(!scannerConsole.hasNext()){
break;
}
String request = scannerConsole.next();
//2.把请求发给服务器
writer.println(request);
writer.flush();
//3.从服务器读取响应
String response = scannerNetwoek.next();
//4.把响应打印出来
System.out.println(response);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws IOException {
TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
client.start();
}