zoukankan      html  css  js  c++  java
  • 详解 ServerSocket与Socket类

    (请观看本人博文 —— 《详解 网络编程》)



    ServerSocket与Socket

    首先,本人来讲解下 ServerSocket 类:

    ServerSocket 类:

    概述

    这个类实现了服务器套接字
    该类是遵循 TCP协议的,所以,必须要和客户端Socket建立连接,才能完成信息的接送
    服务器套接字等待来自网络的请求
    它基于该请求执行某些操作,然后可能向请求者返回结果。
    服务器套接字的实际工作由SocketImpl类的一个实例进行。
    一个应用程序可以更改创建套接字实现的套接字工厂
    配置自己创建适合本地防火墙的套接字

    那么,本人再来展示下这个类的构造方法
    构造方法

    • ServerSocket()
      创建一个绑定服务器套接字
    • ServerSocket(int port)
      创建一个服务器套接字,绑定到指定的端口
    • ServerSocket(int port, int backlog)
      创建一个服务器套接字,并将其绑定到指定的本地端口号,并使用指定的积压
    • ServerSocket(int port, int backlog, InetAddress bindAddr)
      用指定的端口创建一个服务器,听积压,和本地IP地址绑定

    现在,本人再来展示下这个类的API
    API

    • Socket accept()
      监听要对这个套接字作出的连接并接受它
    • void bind(SocketAddress endpoint)
      ServerSocket绑定到一个特定的地址(IP地址和端口号)
    • void bind(SocketAddress endpoint, int backlog)
      ServerSocket绑定到一个特定的地址(IP地址和端口号)
    • void close()
      关闭这个套接字。
    • ServerSocketChannel getChannel()
      返回与此套接字关联的独特的 ServerSocketChannel对象,如果任何
    • InetAddress getInetAddress()
      返回此服务器套接字的本地地址
    • int getLocalPort()
      返回此套接字正在侦听的端口号
    • SocketAddress getLocalSocketAddress()
      返回此套接字绑定到的端点的地址
    • int getReceiveBufferSize()
      得到这个 ServerSocket的 SO_RCVBUF期权的价值,即该缓冲区的大小,将用于接受来自这 ServerSocket插座
    • boolean getReuseAddress()
      如果 SO_REUSEADDR启用
    • int getSoTimeout()
      检索设置 SO_TIMEOUT
    • protected void implAccept(Socket s)
      子类使用此方法重载ServerSocket()返回自己的子类的插座
    • boolean isBound()
      返回的ServerSocket绑定状态
    • boolean isClosed()
      返回的ServerSocket关闭状态
    • void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
      设置此ServerSocket性能偏好
    • void setReceiveBufferSize(int size)
      设置一个默认值为提出接受这 ServerSocket插座 SO_RCVBUF选项
    • void setReuseAddress(boolean on)
      启用/禁用 SO_REUSEADDR套接字选项
    • static void setSocketFactory(SocketImplFactory fac)
      设置服务器套接字实现工厂为应用程序。
    • void setSoTimeout(int timeout)
      启用/禁用 SO_TIMEOUT以指定的超时时间,以毫秒为单位
    • String toString()
      返回此套接字作为 String实现的地址与端口

    由于该类必须与Socket类对象建立连接后才能进行正常的网络通信,所以,本人在讲解完Socket类之后再来展示部分API的使用。


    Socket类:

    概述

    这个类实现了客户端套接字(也被称为“套接字”)
    该类遵循TCP协议,所以必须与ServerSocket建立连接后,才能进行信息的接送
    套接字是两台机器之间的通信的一个端点
    套接字的实际工作是由该类的一个实例进行SocketImpl
    一个应用程序,通过改变创建套接字实现的套接字工厂,可以配置自己创建适合本地防火墙的套接字

    现在,本人来展示下这个类的构造方法
    构造方法

    • Socket()
      创建一个连接的套接字,与socketimpl系统默认的类型。
    • Socket(InetAddress address, int port)
      创建一个流套接字,并将其与指定的IP地址中的指定端口号连接起来。
    • Socket(InetAddress host, int port, boolean stream)
      过时的。
      使用UDP传输DatagramSocket。
    • Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
      创建一个套接字,并将其与指定的远程端口上的指定的远程地址连接起来。
    • Socket(Proxy proxy)
      创建一个连接的套接字类型,指定代理,如果有,应该使用无论任何其他设置。
    • protected Socket(SocketImpl impl)
      创建一个用户指定的socketimpl连接插座。
    • Socket(String host, int port)
      创建一个流套接字,并将其与指定的主机上的指定端口号连接起来。
    • Socket(String host, int port, boolean stream)
      过时的。
      使用UDP传输DatagramSocket。
    • Socket(String host, int port, InetAddress localAddr, int localPort)
      创建一个套接字,并将其连接到指定的远程端口上的指定的远程主机上

    那么,本人再来展示下这个类的API
    API

    • void bind(SocketAddress bindpoint)
      将套接字绑定到本地地址。
    • void close()
      关闭这个套接字。
    • void connect(SocketAddress endpoint)
      将此套接字连接到服务器。
    • void connect(SocketAddress endpoint, int timeout)
      将此套接字与指定的超时值连接到服务器。
    • SocketChannel getChannel()
      返回与此套接字关联的独特的 SocketChannel对象,如果任何。
    • InetAddress getInetAddress()
      返回套接字连接的地址。
    • InputStream getInputStream()
      返回此套接字的输入流。
    • boolean getKeepAlive()
      如果 SO_KEEPALIVE启用。
    • InetAddress getLocalAddress()
      获取绑定的套接字的本地地址。
    • int getLocalPort()
      返回此套接字绑定的本地端口号。
    • SocketAddress getLocalSocketAddress()
      返回此套接字绑定到的端点的地址。
    • boolean getOOBInline()
      如果 SO_OOBINLINE启用。
    • OutputStream getOutputStream()
      返回此套接字的输出流。
    • int getPort()
      返回此套接字连接的远程端口号。
    • int getReceiveBufferSize()
      得到这个 Socket的 SO_RCVBUF选项的值,是由平台用于该 Socket输入缓冲区的大小。
    • SocketAddress getRemoteSocketAddress()
      返回此套接字连接的端点的地址,或如果它是无关的 null。
    • boolean getReuseAddress()
      如果 SO_REUSEADDR启用。
    • int getSendBufferSize()
      得到这个 Socket的 SO_SNDBUF期权价值,即缓冲区的大小由平台用于输出在这 Socket。
    • int getSoLinger()
      返回设置 SO_LINGER。
    • int getSoTimeout()
      返回设置 SO_TIMEOUT。
    • boolean getTcpNoDelay()
      如果 TCP_NODELAY启用。
    • int getTrafficClass()
      获取从这个套接字发送的数据包的IP头中的业务类或服务类型
    • boolean isBound()
      返回套接字的绑定状态。
    • boolean isClosed()
      返回套接字的关闭状态。
    • boolean isConnected()
      返回套接字的连接状态。
    • boolean isInputShutdown()
      返回套接字连接的读半是否关闭。
    • boolean isOutputShutdown()
      返回套接字连接的写是否关闭的是否关闭。
    • void sendUrgentData(int data)
      在套接字上发送一个字节的紧急数据。
    • void setKeepAlive(boolean on)
      启用/禁用 SO_KEEPALIVE。
    • void setOOBInline(boolean on)
      启用/禁用 SO_OOBINLINE(TCP紧急数据收据)默认情况下,此选项是禁用TCP套接字上接收紧急数据是默默丢弃。
    • void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
      设置此套接字的性能首选项。
    • void setReceiveBufferSize(int size)
      集 SO_RCVBUF选项,这 Socket指定值。
    • void setReuseAddress(boolean on)
      启用/禁用 SO_REUSEADDR套接字选项。
    • void setSendBufferSize(int size)
      设置这个 Socket指定值的 SO_SNDBUF选项。
    • static void setSocketImplFactory(SocketImplFactory fac)
      设置客户端套接字实现工厂的应用程序。
    • void setSoLinger(boolean on, int linger)
      启用/禁用 SO_LINGER与指定的逗留的时间秒。
    • void setSoTimeout(int timeout)
      启用/禁用 SO_TIMEOUT以指定的超时时间,以毫秒为单位。
    • void setTcpNoDelay(boolean on)
      启用/禁用 TCP_NODELAY(禁用/启用Nagle的算法)。
    • void setTrafficClass(int tc)
      集交通类或从该套接字发送数据包的IP报头字节型服务。
    • void shutdownInput()
      将此套接字的输入流放在“流结束”中。
    • void shutdownOutput()
      禁用此套接字的输出流。
    • String toString()
      将这一 String插座

    那么,现在,本人来通过两个例子来展示下这两个类的使用:
    例1

    题目
    这天右转哥玩游戏的时候,意外发现了游戏的一个Bug,于是,就向游戏公司发送信息,准备上报这个Bug
    要求
    编写一个服务器端的代码,再编写一个客户端的代码,完成客户端向服务器端的Bug上报

    那么,本人来展示下代码:

    首先是服务器端的代码:

    package edu.youzg.about_net.about_tcp.core;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
    
        public static void main(String[] args) throws IOException {
            ServerSocket ss = new ServerSocket(6666);
            System.out.println("服务器已经开启,等待连接。。。");
            Socket sk = ss.accept();
            //循环读取客户端发来的消息
            while (true){
                InputStream in = sk.getInputStream();
                String ip = sk.getInetAddress().getHostAddress();
                byte[] bytes = new byte[1024];
                int len = in.read(bytes);
                String s = new String(bytes, 0, len);
                if(s.equals("byebye")){
                    break;
                }
                System.out.println(ip+":给你发来消息内容是:"+s);
            }
            ss.close();
        }
    
    }
    

    现在是客户端的代码:

    package edu.youzg.about_net.about_tcp.core;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;
    
    public class TCPClient {
    
        public static void main(String[] args) throws IOException {
            //客户端键盘录入服务器控制台输出
            Socket sk = new Socket("localhost", 6666);
            BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
            while (true){
                System.out.println("请输入消息");
                String msg= bfr.readLine();
                //发送给服务端
                OutputStream out= sk.getOutputStream();
                out.write(msg.getBytes());
                if ("byebye".equals(msg)) {
                    break;
                }
            }
            //释放资源
            bfr.close();
        }
    
    }
    

    那么,现在,本人再来展示下运行结果

    首先是客户端的控制台:
    在这里插入图片描述

    接下来是服务器端的控制台:
    在这里插入图片描述


    例2

    题目
    有一个壁纸很好康,右转哥的两个朋友十分想要,但是在网上找不到,朋友电脑上只有能运行Java程序的App,所以只能求右转哥想办法
    要求
    通过网络编程所学知识,将目标图片传送至那两个朋友的电脑上

    首先是 一个能够上传文件的线程实现类:

    package edu.youzg.about_net.upload_file.core;
    
    import java.io.*;
    import java.net.Socket;
    
    public class ServerThread extends Thread{
        Socket sk;
        public ServerThread(Socket sk) {
            this.sk=sk;
        }
    
        @Override
        public void run() {
            try {
                InputStream in = sk.getInputStream();
                OutputStream out = sk.getOutputStream();
                BufferedWriter bfw = new BufferedWriter(new FileWriter(System.currentTimeMillis() + "copyFile.txt"));   //由于本人只有一台电脑,所以就将文件名跟事件相关
                //包装一下输入流
                BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
                String line = null;
                while ((line = bfr.readLine()) != null) {
                    bfw.write(line);
                    bfw.newLine();
                    bfw.flush();
                }
                //告诉客户端,文件上传成功
                out.write("文件上传成功".getBytes());
    
                bfw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    那么,本人先来展示下右转哥要运行的代码:

    package edu.youzg.about_net.upload_file.core;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
    
        public static void main(String[] args) throws IOException {
            //服务器告诉浏览器上传成功了
            ServerSocket ss = new ServerSocket(5555);
            System.out.println("服务器已经开启。。。");
            int i=1;
            while (true){
                Socket sk = ss.accept(); //侦听客户端
                System.out.println((i++)+"个客户端已经连接");
                //为每一个客户端,开启一个线程,去处理
                new ServerThread(sk).start();
            }
        }
    
    }
    

    接下来,本人再来展示下两个朋友要运行的代码:

    package edu.youzg.about_net.upload_file.core;
    
    import java.io.*;
    import java.net.Socket;
    
    public class TCPClient {
    
        public static void main(String[] args) throws IOException {
            //给服务上传一个文本文件
            Socket socket = new Socket("localhost", 5555);
            //获取通道中的输入输出流
            InputStream in= socket.getInputStream();
            OutputStream out = socket.getOutputStream();
            //读取文本文件
            BufferedReader bfr = new BufferedReader(new FileReader("test.txt"));
            String line=null;
            //把通道中的输出流包装一下
            BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
            while ((line=bfr.readLine())!=null){
                bfw.write(line);
                bfw.newLine();
                bfw.flush();
            }
            //禁用此套接字的输出流。
            socket.shutdownOutput();
            //读取服务端反馈
            byte[] bytes = new byte[1024];
            int len = in.read(bytes);//阻塞式方法
    
            String s = new String(bytes, 0, len);
            System.out.println(s);
            //释放资源
            bfr.close();
            socket.close();
    
        }
    
    }
    

    那么,现在,本人来展示下运行结果:
    首先,本人来展示下源文件的目录信息和源文件内容:
    在这里插入图片描述
    现在,本人来展示下运行后所生成的文件和该文件的内容:
    在这里插入图片描述
    在这里插入图片描述
    那么,可以看到,我们将文件上传成功了!


    (本人 网络编程 总集篇博文链接:https://www.cnblogs.com/codderYouzg/p/12419011.html)

  • 相关阅读:
    java基础(7)
    log4j日志打印级别动态调整
    前端学习
    windows下 使用vs command tools 和mingw 分别编译 openssl
    收尾作业(3)
    收尾作业(2)
    收尾作业(1)
    收尾作业第一个接口
    图形建模需求
    收尾作业2
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12419038.html
Copyright © 2011-2022 走看看