Socket套接字

套接字 Socket = (IP地址:端口号)。它唯一地标识网络中地一台主机和其上的一个应用(进程)。在网络中通过IP地址来标识和区别不同地主机,通过端口号来标识和区分一套主机中的不同应用进程,端口号拼接到IP地址即可构成套接字。

要实现Socket通信,我们必须创建一个数据发送者和一个数据接收者,也就是客户端和服务端,我们需要提前启动服务端,来等待客户端的连接,而客户端只需要随时启动去连接服务端即可!

套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。
java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。

服务器端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public  static void main(String[] args) {
        try{
            ServerSocket server = new ServerSocket(8085);
            while (true) {
                System.out.println("等待客户端连接...");
                server.setSoTimeout(5000);
                Socket socket = server.accept();
                System.out.println("连接客户端成功,IP地址为:" + socket.getInetAddress().getHostAddress());
                //System.out.println(socket.getInetAddress());

                System.out.println("读取客户端数据:");

                // 此套接字的输入流,就是所连接客户端的输出流,那就相当于是从客户端读取数据
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                System.out.println(reader.readLine());

                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                writer.write(socket.getPort() + " hey bro! accepted.\n");
                writer.flush();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端:

import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        try{
            Socket client = new Socket("localhost", 8085);
            System.out.println("成功连接到服务器!");
            System.out.println("连接客户端成功,IP地址为:" + client.getInetAddress().getHostAddress());

            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
            writer.write("hey bro! nb!\n");

            // 清缓存,把数据直接发送给服务器
            writer.flush();

            BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            //System.out.println(reader.read());
            System.out.println(reader.readLine());
            client.setKeepAlive(true);
        }catch (IOException e) {
            System.out.println("连接服务器失败!");
            e.printStackTrace();
        }finally {
            System.out.println("与服务器连接断开!");
        }
    }
}

SocketServer类常用的方法

// 四个构造方法
// 创建非绑定服务器套接字
public ServerSocket() throws IOException

// 创建绑定到特定端口的套接字
public SocketServer(int port) throws IOException

// 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
public SocketServer(int port,int backlog) throws IOException

// 返回此套接字在其上侦听的端口
public int getLocalPort()

// 侦听并接收到此套接字的连接
public Socket accept() throws IOException

// 设置超时时间,以毫秒为单位,超过此时间还未成功等待响应时则抛出异常
public void setSoTimeout(int timeout);

java.net.Socket 类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象通过实例化 ,而 服务器获得一个 Socket 对象则通过 accept() 方法的返回值。

Socket类的方法:

// Socket的构造方法
public Socket()

// 创建一个流套接字并将其连接到指定主机上的指定端口号。
public Socket(String host, int port) throws UnknownHostException, IOException

public Socket(InetAddress host, int port) throws IOException

public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException

public Socket(InetAddress host, int port, InetAddress localAddress, int LocalPort) throws IOException

// 将此套接字连接到服务器,并指定一个超时值。
public void connect(SocketAddress host, int timeout) throws IOException

// 返回此套接字连接到的远程端口。
public int getPort()

// 返回套接字连接的地址
public InetAddress getInetAddress()

public int getLocalPort()

// 返回此套接字的输入流
public InputStream getInputStream() throws IOException

// 关闭套接字
public void close() throws IOException

socket.shutdownOutput();  //关闭输出方向的流
socket.shutdownInput();   //关闭输入方向的流

socket..setKeepAlive(true);
/* 判断所连接的对方是否还正常,如果很长时间双方都没有发生交互时,我们会发送一个ack探测包发送到对方,探测TCP/IP连接是否还存在 */

InetAddress类表示IP地址。该类有以下常用方法:

// 返回本地主机,静态方法
static InetAddress getLocalHost();

// 在给定原始 IP 地址的情况下,返回 InetAddress 对象。
static InetAddress getByAddress(byte[] addr)
// 在给定主机名的情况下确定主机的 IP 地址。
static InetAddress getByName(String host)

// 将ip地址转换为字符串
public String toString()

// 获取此IP地址的用户名
String getHostName();

// 返回IP地址
String getHostAddress();
缓冲区

建立TCP/IP连接的双发都会设置一个发送缓冲区和接收缓冲区,此缓冲去大小为8192KB,可以手动设置。所以想要立刻把数据发送给对方时,最好在发送完之后执行socket.flush()语句,把缓冲区内的内容全都发送了。

socket.setReceiveBufferSize(25536);    //设置接收缓冲区
socket.setSendBufferSize(25535);       //设置发送缓冲区

(图盗,侵删)

使用Socket传输文件

任何文件都可以以字节流的方式进行读写,因为数据都是以字节为单位的。

服务器端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public  static void main(String[] args) {
        try{
            ServerSocket server = new ServerSocket(8085);

            ;

            while (true) {
                System.out.println("等待客户端连接...");
                //server.setSoTimeout(5000);
                Socket socket = server.accept();
                System.out.println("连接客户端成功,IP地址为:" + socket.getInetAddress().getHostAddress());

                System.out.println("读取客户端数据...");

                // 新建一个文件输出流,用来写入指定的文件
                FileOutputStream stream = new FileOutputStream(args[0]);

                // 输入流,读取从客户端发送来的数据
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1024];
                int i;
                while ( (i=inputStream.read(bytes))!=-1 ) {
                    stream.write(bytes, 0, i);
                    //stream.write(55);
                }

                inputStream.close();
                stream.close();

                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器端程序需要两个参数:端口号,需要写入的文件名称

注意对文件的操作完成之后一定要把流关闭掉,否则会损坏文件。

客户端:

import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        try{
            Socket client = new Socket(args[0], args[1]);
            System.out.println("成功连接到服务器!");
            System.out.println("连接客户端成功,IP地址为:" + client.getInetAddress().getHostAddress());

            // 创建一个文件读取字节流,以第三个参数为文件名
            FileInputStream fileInputStream = new FileInputStream(arge[2]);
            // 创建一个文件输出字节流,这里写的东西会传输到服务器的输入流
            OutputStream stream = client.getOutputStream();
            byte[] bytes = new byte[1024];
            int i;
            while ( ( i = fileInputStream.read(bytes)) != -1 ) {
                // 写bytes数组,从0开始的长度为i的字节流
                stream.write(bytes, 0, i);
            }
            stream.flush();
            stream.close();
            fileInputStream.close();

            // 清缓存,把数据直接发送给服务器
            writer.flush();

            client.setKeepAlive(true);
        }catch (IOException e) {
            System.out.println("连接服务器失败!");
            e.printStackTrace();
        }finally {
            System.out.println("与服务器连接断开!");
        }
    }
}

客户端程序的调用需要三个参数:服务器ip地址,端口号,读取的文件地址。

上述两个程序会将客户端的一个文件传输到服务器端。程序调用命令如下

java Server 8085 H:\xanadu.txt
java Client 10.163.181.251 8085 C:\Users\28158\Desktop\xanadu.txt
分类: Java Web

1 条评论

匿名 · 2026年1月29日 下午6:02

匿名进行回复 取消回复

邮箱地址不会被公开。