1.Server and client
server
我们经常需要关闭一些实例,比如server,所以我们使用这个接口,来实现自动关闭。
我们可以这样写,手动关闭server
public class Server {public static void main(String args[]){try {ServerSocket server = new ServerSocket(8080);//accept() will block the thread until the clint send a request// accept() will return a socket represent the clientSystem.out.println("connecting...");Socket socket1=server.accept();System.out.println("IP address:"+socket1.getInetAddress().getHostAddress());//If you do not close the server, the port will be occupied and you are not able to use the portserver.close();}catch(IOException e){e.printStackTrace();}}
}
也可以这样写进try catch语句,自动关闭:
public static void main(String args[]){try(ServerSocket server = new ServerSocket(8080)) {//accept() will block the thread until the clint send a request// accept() will return a socket represent the clientSystem.out.println("connecting...");Socket socket1=server.accept();System.out.println("IP address:"+socket1.getInetAddress().getHostAddress());//If you do not close the server, the port will be occupied and you are not able to use the port}catch(IOException e){e.printStackTrace();}}
}
try后括号里的内容需要实现autocloseable 接口。
client
import java.io.IOException;
import java.net.Socket;public class Client {public static void main(String[] args) {//if you run on your own computer, then you can use "localhost"//if you run in the local area network(LAN), use "ipconfig" to see your sourcetry(Socket socket = new Socket("localhost",8080)){//here is the same way as Server//socket should close and I write it in try block}catch(IOException e){e.printStackTrace();}}
}
先运行server,再运行client,server在client运行之前,会一直监听端口。
这实际上是tcp的握手过程,只不过java全部封装了。
接受多个client
用while循环就行了
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class Server {public static void main(String args[]){try(ServerSocket server = new ServerSocket(8080)) {//accept() will block the thread until the clint send a request// accept() will return a socket represent the clientSystem.out.println("connecting...");while (true){Socket socket1=server.accept();System.out.println("IP address:"+socket1.getInetAddress().getHostAddress());}//If you do not close the server, the port will be occupied and you are not able to use the port}catch(IOException e){e.printStackTrace();}}
}
这里的client和server是怎么联系的呢?
我们在client里创建了一个socket,给这个socket指定端口8080,然后我们在server里创建一个
ServerSocket,通过监听8080端口来连接这个socket。同时,把这个监听到的socket又通过accept接受为一个本地的socket,在例子里命名为socket1.这个本地化的socket1其实和client里的socket是连接的,但是名字可以不一样。
-
server.accept()
:这是在服务器端Socket编程中的一种操作,其中server
是一个ServerSocket对象。ServerSocket对象通常在服务器端用于监听特定的网络端口,以便接受客户端的连接请求。accept()
方法是一个阻塞调用,它会等待客户端的连接请求,一旦有客户端连接请求到达,它会接受这个连接请求,并返回一个新的Socket对象,该Socket对象代表与客户端建立的连接。 -
Socket socket1=server.accept();
:这行代码执行了accept()
方法,并将返回的Socket对象存储在变量socket1
中。这个socket1
对象表示与一个特定客户端建立的连接,可以使用它进行双向通信,即从客户端接收数据和向客户端发送数据。
2.客户端发送数据
client
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;public class Client {public static void main(String[] args) {//if you run on your own computer, then you can use "localhost"//if you run in the local area network(LAN), use "ipconfig" to see your sourcetry(Socket socket = new Socket("localhost",8080);Scanner scanner=new Scanner(System.in)){ //Scanner also need to close, so write scanner in try blockSystem.out.println("Already connected to the server!");System.out.println("write something that I can send to server:");//this is a convert stream// it is more convenient than socket.getOutputStream()OutputStreamWriter writer=new OutputStreamWriter(socket.getOutputStream());writer.write(scanner.nextLine()+"\n");//flush and client will send it to serverwriter.flush();//here is the same way as Server, "socket" should close and I write it in try blockSystem.out.println("data already sent");}catch(IOException e){System.out.println("fail to connect to server");e.printStackTrace();}}
}
注意
OutputStreamWriter writer=new OutputStreamWriter(socket.getOutputStream()); writer.write(scanner.nextLine()+"\n");
这行代码创建了一个OutputStreamWriter对象,该对象连接到给定的套接字(socket)的输出流,以便将字符数据写入该套接字,所以我可以向OutputStreamWriter写入数据,写的数据会被放到套接字(socket)的输出流。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class Server {public static void main(String args[]){try(ServerSocket server = new ServerSocket(8080);) {//accept() will block the thread until the clint send a request// accept() will return a socket represent the clientSystem.out.println("connecting...");while (true){Socket socket1=server.accept();System.out.println("IP address:"+socket1.getInetAddress().getHostAddress());System.out.println("reading data...");//BufferedReader easy to output the dataBufferedReader reader=new BufferedReader(new InputStreamReader(socket1.getInputStream()));//socket need to close and did not write in try block//so need to close hereSystem.out.println(reader.readLine());socket1.close();}//If you do not close the server, the port will be occupied and you are not able to use the port}catch(IOException e){e.printStackTrace();}}
}
同理
BufferedReader reader=new BufferedReader(new InputStreamReader(socket1.getInputStream()));
这行代码创建了一个BufferedReader对象,该对象连接到给定的套接字(socket1)的输入流,以便以字符流的方式从套接字中读取数据