Socket编程

Socket 套接字概念

  • 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

  • 建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

  • Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。客户软件将插头插到不同编号的插座,就可以得到不同的服务。



利用Socket建立网络连接的步骤


套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

  • 1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

  • 2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。   为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

  • 3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。

  • 而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。



简单了解了Socket的原理之后我们知道:

  • 1、两个程序进行通信是通过端口号进行连接的
  • 2、客户端要访问服务器是需要一个ip地址和一个端口的
  • 3、每一次只能发送一条数据


为了更理解Socket套接字,必须要先理解Java中的IO流:

http://blog.csdn.net/gfd54gd5f46/article/details/54936972


ServerSocket类


serverSocket在线API: http://www.apihome.cn/api/java/serverSocket.html



使用serverSocket创建服务端

  • 构造函数:
ServerSocket(int port)     创建绑定到特定端口的服务器套接字。
  • 方法:
Socket accept()   侦听并接受到此套接字的连接。

  • 服务端代码实现
    /**
     * 服务器
     */
    public static void test1() {
        try {
            System.out.println("服务已经启动,监听端口8888");
            //创建一个服务端,监听端口8888
            ServerSocket serverSocket = new ServerSocket(8888);
            //等待客户端连接过来
            Socket socket = serverSocket.accept();
            System.out.println("来客IP:" + socket.getInetAddress());
            //socket.getOutputStream() 获取客服端的输出流
            OutputStream os = socket.getOutputStream();
            //socket.getInputStream() 获取客服端的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            //用来给客户端发送消息
            PrintWriter pw = new PrintWriter(os);
            pw.println("welcome to my home");
            pw.flush();
            String line = "";
            while(true){
                line = br.readLine();
                System.out.println(line);
                if (line.equals("exit")) {
                    System.out.println("拜拜");
                    break;
                }
            }

            os.close();
            pw.close();
            br.close();
            serverSocket.close();

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

这样就成功开启了一个服务端了

1


然后我们用telnet连接一下

telnet 192.168.20.168 8888

2


输入ctrl + ] 就可以发送信息了

3


我现在输入 一段话过去

4


服务端就接收到了信息

5


客服端向服务器发送 exit

6


服务器端接收就退出了

7

这样一个简单的服务器端就制作好了



实现对讲机功能



特点是一个说完,另一个才能说,一问一答

  • 代码实现
/**
     * 模拟对讲机效果。特点是一个说完,另一个才能说,一问一答
     */
    public static void test4() {
        //创建一个服务端
        System.out.println("服务已经启动,监听端口8888");
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            //接受一个客户端
            Socket socket = serverSocket.accept();


            //服务端的输入流,服务器端的scanner
            Scanner serverKeybordScanner = new Scanner(System.in);
            //服务端的输出流
            PrintWriter serverPw = new PrintWriter(socket.getOutputStream());


            //客户端的输入流
            Scanner clientScanner = new Scanner(socket.getInputStream());


            //如果客户端的输入流有下一行
            while(clientScanner.hasNextLine()){
                String msg = clientScanner.nextLine();
                System.out.println("客服端的输入:" + msg);
                if (msg.equals("exit")) {
                    break;
                }
                //每次客户端输入一段话过来,我们都要从键盘输入一段话,并且发送给客服端
                if (serverKeybordScanner.hasNextLine()) {
                    //输入一段话
                    String serverMsg = serverKeybordScanner.nextLine();
                    //System.out.println("服务器输入:" + serverMsg);
                    //发送给客户端
                    serverPw.println("服务器 :" + serverMsg);
                    serverPw.flush();
                }

            }

            serverPw.close();
            serverKeybordScanner.close();
            clientScanner.close();
            serverSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

8


使用telnet做为我们的客户端连接一下


这时客户端发送一个数据过去:hello I am Client

9


服务端获取到数据之后,回复一下

10


客户端接收到服务端的消息,并发送exit到服务器

11


服务器接收到exit之后程序就结束了

12

这样一个简单的对讲机功能就实现了


模拟一个获取内容的木马
  • 客户端发送一个 文件的绝对路径 到服务端

  • 服务端接收到文件路径之后将文件的内容返回给客户端


为了方便测试我在项目目录下创建了一个 test.txt 的文件

13

  • 代码实现
    /**
     * 服务端
     * 用来获取文件的绝对路径
     * 客户端输入一个文件名,服务端就把指定的文件的内容返回给客户端
     */
    public static void test5() {
        System.out.println("服务器开启!");
        //1、创建一个服务端,监听一个端口
        ServerSocket serverSocket;
        Socket socket = null;
        try {
            serverSocket = new ServerSocket(8888);
            //2、获取一个客户端的对象
            socket = serverSocket.accept();
            //打印输出客服端的IP地址
            System.out.println("来客IP:" + socket.getInetAddress());
            //拿到用户的输入流
            Scanner scanner = new Scanner(socket.getInputStream());
            //拿到用户的输出流
            PrintWriter pw = new PrintWriter(socket.getOutputStream());
            //如果捕获到有下一行
            while(scanner.hasNextLine()){
                //3、接受客服端的一个文件名(绝对路径)
                String fileName = scanner.nextLine();
                //4、读取文件
                String content = getContentFromFile(fileName);
                //5、把文件返回给客户端
                pw.println(content);
                //刷新
                pw.flush();
            }
            scanner.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 从文件路径中找到文件并获取内容
     * @param fileName
     * @return content
     */
    public static String  getContentFromFile(String fileName) {
        StringBuffer content = new StringBuffer();

        Scanner scanner;
        try {
            scanner = new Scanner(new FileInputStream(fileName),"UTF-8");
            while (scanner.hasNextLine()) {
                content.append(scanner.nextLine()).append("\n");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return content.toString();
    }

这样就开启了一个服务端

14


使用telnet连接一下,服务器捕获到了连接

15


然后输入test.txt 文件名 就获取到了内容

16




Socket类


         刚刚介绍了一个服务端的创建过程,里面都是使用telnet作为我们的客户端进行交互,那我们能不能自己制作一个客户端呢?




一对一聊天功能的实现


Socket在线API: http://www.apihome.cn/api/java/Socket.html

  • 构造方法:
Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
  • 方法:
InputStream getInputStream() 返回此套接字的输入流。


OutputStream getOutputStream() 返回此套接字的输出流。


创建Server项目

/**
 * 服务器端
 * 端口7777
 * @author Lingdu
 *
 */
public class Server {

    /**
     * 开启一个服务器
     */
    public static void openServer() {
        System.out.println("服务器已开启!");
        try {
            //服务器的端口
            ServerSocket serverPort = new ServerSocket(7777);
            //等待一个客服端的连接
            Socket client = serverPort.accept();

            //拿到用户的输入流
            DataInputStream clientDis = new DataInputStream(client.getInputStream());
            //拿到用户的输出流
            DataOutputStream clientDos = new DataOutputStream(client.getOutputStream());

            //服务器自己的输入流
            BufferedReader myBf = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));


            while(true){
                //读取来自客户端的信息
                String clientMsg = clientDis.readUTF();
                if (!clientMsg.equals("")) {
                    System.out.println("客服端说:" + clientMsg + "\n");
                    if (clientMsg.equals("exit")) {
                        break;
                    }
                    System.out.print("请输入:");
                    String serverSend = myBf.readLine();
                    clientDos.writeUTF((serverSend));
                    clientDos.flush();
                }
            }
            client.close();
            clientDis.close();
            clientDos.close();
            myBf.close();
            serverPort.close();
        } catch (IOException e) {
            System.err.println(e.toString());
        }
    }

    public static void main(String[] args) {
        openServer();
    }
}

17



创建Client项目

package com.lingdu.client;


import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;


import java.net.Socket;


/**
 * 客户端
 * @author LingDu
 *
 */
public class Client {
    public static void myClient(String host,int port) {
        try {
            //通过IP跟端口连接到服务器
            Socket socket = new Socket(host, port);
            //拿到服务器的输入流
            DataInputStream serverDis = new DataInputStream(socket.getInputStream());
            //拿到服务器的输出流
            DataOutputStream serverDos = new DataOutputStream(socket.getOutputStream());

            //客户端自己的输入流
            BufferedReader myBf = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));

            while(true){
                System.out.print("请输入:");
                String clientSend = myBf.readLine();
                serverDos.writeUTF((clientSend));
                serverDos.flush();

                //读取来自服务器的消息serverDis.readUTF();
                String serverMsg = serverDis.readUTF();
                System.out.println("服务器说:" + serverMsg + "\n");
                if (serverMsg.equals("exit")) {
                    break;
                }   
            }
            socket.close();
            serverDis.close();
            serverDos.close();
            myBf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        myClient("192.168.20.163",7777);
    }
}


运行之后 服务端就接收到了连接

18



此时客户端进入输入状态,可以向服务器发送一条信息

19



服务器接收到客户端的信息

  • 此时服务端进入输入状态,可以向客户端回复一条信息

20



客户端收到服务端的回复

  • 这时客户端又会进入输入状态

21

这样一个简单的聊天软件就实现了。




总结

  • Socket是一种常连接,是 半双工1 的数据传输

  • Socket套接字在平常的的业务开发中并不会使用到,因为它会有很多缺陷,这个教程是为了帮助我们更好的去理解网络的概念。






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值