MENU

Socket

July 1, 2018 • Read: 5067 • Java阅读设置

Socket

  • 据交换,这个双向连接的一端称为一个 Socket
  • java.net 包中定义的两个类 Socket 和 ServerSocket,分别用来实现双向连接的 client 和 server 端
  • 建立连接时所需的寻址信息为远程计算机的 ip 地址和端口号(Port number)
  • //Server端
  • import java.net.*;
  • import java.io.*;
  • public class TcpServer {
  • public static void main(String[] args) throws Exception{
  • ServerSocket ss = new ServerSocket(6666);
  • while(true) {
  • Socket s = ss.accept();
  • DataInputStream dis = new DataInputStream(s.getInputStream());
  • System.out.println(dis.readUTF());
  • dis.close();
  • s.close();
  • }
  • }
  • }
  • //Client端
  • import java.io.*;
  • import java.net.*;
  • public class TcpClient {
  • public static void main(String[] args) throws Exception{
  • Socket s = new Socket("127.0.0.1",6666);
  • OutputStream os = s.getOutputStream();
  • DataOutputStream dos = new DataOutputStream(os);
  • dos.writeUTF("Hello Server");
  • dos.flush();
  • dos.close();
  • }
  • }

首先说 Server 端,Server 端用的类是 ServerSocket,构造方法中的参数表示监听哪个端口,一个服务器或者一台电脑上有很多端口,其中有一些是已经被占用的,就不能用,这里我随便用 6666 这个端口

然后是 Client 端,Client 端用的类是 Socket,构造方法中的两个参数,第一个是访问的 ip,127.0.0.1 代表的 ip 表示本机,也可以用 localhost 替换,第二个参数代表访问 Server 端的哪个端口

随后 Client 端通过流,向 Server 端发送消息,Server 端调用 accept 方法首先允许 Client 端访问,然后也通过流读入 Client 发送的消息,整个过程是个死循环,模拟真实服务器 24 小时不间断的操作

  • //Server端
  • import java.net.*;
  • import java.io.*;
  • public class TestServer {
  • public static void main(String[] args) {
  • try {
  • ServerSocket s = new ServerSocket(6666);
  • while(true) {
  • Socket s1 = s.accept();
  • OutputStream os = s1.getOutputStream();
  • DataOutputStream dos =
  • new DataOutputStream(os);
  • dos.writeUTF("Hello," + s1.getInetAddress() + ",Port#" + s1.getPort());
  • dos.close();
  • s1.close();
  • }
  • }catch (IOException e) {
  • e.printStackTrace();
  • System.out.println("程序运行错误:" + e);
  • }
  • }
  • }
  • //Client端
  • import java.io.*;
  • import java.net.*;
  • public class TestClient {
  • public static void main(String[] args) {
  • try {
  • Socket s = new Socket("localhost",6666);
  • InputStream is = s.getInputStream();
  • DataInputStream dis =
  • new DataInputStream(is);
  • System.out.println(dis.readUTF());
  • dis.close();
  • s.close();
  • }catch(IOException e) {
  • e.printStackTrace();
  • System.out.println("服务器连接超时" + e);
  • }
  • }
  • }

上面的程序不再是 Client 向 Server 端发送消息,而是 Server 端向 Client 端发送消息,在 Server 端中输出代码里,有一个方法 getInetAddress,这个返回的不是 Serveer 端的 ip,返回的是 Client 端的 IP

其次,getPort 方法返回的是 Client 出来的端口号,Client 使用哪个端口是系统随机分配的,而 Server 端开发什么端口是自定义的,这两个有区别

  • //Server端
  • import java.net.*;
  • import java.io.*;
  • public class TestSocketServer {
  • public static void main(String[] args) {
  • InputStream in = null;
  • OutputStream out = null;
  • try {
  • ServerSocket s = new ServerSocket(6666);
  • Socket s1 = s.accept();
  • in = s1.getInputStream();
  • out = s1.getOutputStream();
  • DataOutputStream dos = new DataOutputStream(out);
  • DataInputStream dis = new DataInputStream(in);
  • String ss = null;
  • if((ss = dis.readUTF()) != null) {
  • System.out.println(s);
  • System.out.println("from:" + s1.getInetAddress());
  • System.out.println("Port:" + s1.getPort());
  • }
  • dos.writeUTF("Hello");
  • dis.close();
  • dos.close();
  • s1.close();
  • }catch(IOException e) {
  • e.printStackTrace();
  • }
  • }
  • }
  • //Client端
  • import java.net.*;
  • import java.io.*;
  • public class TestSocketClient {
  • public static void main(String[] args) {
  • InputStream is = null;
  • OutputStream os = null;
  • try {
  • Socket s = new Socket("localhost",6666);
  • is = s.getInputStream();
  • os = s.getOutputStream();
  • DataInputStream dis = new DataInputStream(is);
  • DataOutputStream dos = new DataOutputStream(os);
  • dos.writeUTF("hey");
  • String ss = null;
  • if((ss = dis.readUTF()) != null) {
  • System.out.println(ss);
  • }
  • dis.close();
  • dos.close();
  • s.close();
  • }catch(IOException e){
  • e.printStackTrace();
  • }
  • }
  • }

上面的程序实现了 Server 和 Client 相互传输信息

聊天小程序

  • import java.net.*;
  • import java.io.*;
  • public class TalkServer {
  • public static void main(String[] args) {
  • try {
  • ServerSocket server = new ServerSocket(6666);
  • Socket socket = server.accept();
  • String line = null;
  • BufferedReader br =
  • new BufferedReader(
  • new InputStreamReader(socket.getInputStream()));
  • PrintWriter pw =
  • new PrintWriter(socket.getOutputStream());
  • BufferedReader br1 =
  • new BufferedReader(
  • new InputStreamReader(System.in));
  • System.out.println("Client:" + br.readLine());
  • line = br1.readLine();
  • while(!line.equals("exit")) {
  • pw.println(line);
  • pw.flush();
  • System.out.println("Server:" + line);
  • System.out.println("Client:" + br.readLine());
  • line = br1.readLine();
  • }
  • br.close();
  • br1.close();
  • pw.close();
  • server.close();
  • socket.close();
  • }catch(Exception e) {
  • e.printStackTrace();
  • }
  • }
  • }
  • import java.net.*;
  • import java.io.*;
  • public class TalkClient {
  • public static void main(String[] args) {
  • try {
  • Socket socket = new Socket("localhost",6666);
  • BufferedReader br =
  • new BufferedReader(
  • new InputStreamReader(System.in));
  • PrintWriter pw =
  • new PrintWriter(socket.getOutputStream());
  • BufferedReader br1 =
  • new BufferedReader(
  • new InputStreamReader(socket.getInputStream()));
  • String readLine;
  • readLine = br.readLine();
  • while(!readLine.equals("exit")){
  • pw.println(readLine);
  • pw.flush();
  • System.out.println("Client:" + readLine);
  • System.out.println("Server:" + br1.readLine());
  • readLine = br.readLine();
  • }
  • br.close();
  • br1.close();
  • pw.close();
  • socket.close();
  • }catch(Exception e) {
  • e.printStackTrace();
  • }
  • }
  • }

补充

accept 和 readUTF 方法是阻塞式的,也就是说如果没有 Client 向 Server 端发送消息或者访问端口,Server 就会一直等待,不会执行下面的语句

Last Modified: November 9, 2021
Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment

2 Comments
  1. noah noah

    1

    1. mathor mathor

      @noah