socket教程

1、socket

      在OSI七层网络模型中,Socke接口处于OSI 七层模型的表示层,利用socket接口编程的代码处于应用层

这里写图片描述

 

Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议

 

2、linux和windows中的socket

2.1、unix/linux中的socket

unix/linux中的一切都是文件

在 UNIX/Linux 系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作

为了表示和区分已经打开的文件,UNIX/Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。例如:
    通常用 0 来表示标准输入文件(stdin),它对应的硬件设备就是键盘;
    通常用 1 来表示标准输出文件(stdout),它对应的硬件设备就是显示器。

UNIX/Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。
请注意,网络连接也是一个文件,它也有文件描述符!

 通过 socket() 函数可与来创建一个网络连接,或者说打开一个网络文件,socket() 的返回值就是文件描述符。有了文件描述符,我们就可以使用普通的文件操作函数来传输数据了,例如:
用 read() 读取从远程计算机传来的数据;
用 write() 向远程计算机写入数据。

只要用 socket() 创建了连接,剩下的就是文件操作了

 

2.2、windows中的socket

Windows 也有类似“文件描述符”的概念,但通常被称为“文件句柄”

与 UNIX/Linux 不同的是,Windows 会区分 socket 和文件,Windows 就把 socket 当做一个网络连接来对待,因此需要调用专门针对 socket 而设计的数据传输函数,针对普通文件的输入输出函数就无效了

 

3、套接字分类 

流格式套接字(SOCK_STREAM)也叫面向连接的套接字,基于TCP

数据报格式套接字(SOCK_DGRAM)也叫“无连接的套接字”,基于UDP

QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 来传输数据,因为首先要保证通信的效率,尽量减小延迟,而数据的正确性是次要的,即使丢失很小的一部分数据,视频和音频也可以正常解析,最多出现噪点或杂音,不会对通信质量有实质的影响。

注意:SOCK_DGRAM 没有想象中的糟糕,不会频繁的丢失数据,数据错误只是小概率事件

 

4、MAC地址

现实的情况是,一个局域网往往才能拥有一个独立的 IP;换句话说,IP 地址只能定位到一个局域网,无法定位到具体的一台计算机。这可怎么办呀?这样也没法通信啊。

其实,真正能唯一标识一台计算机的是 MAC 地址,每个网卡的 MAC 地址在全世界都是独一无二的。计算机出厂时,MAC 地址已经被写死到网卡里面了(当然通过某些“奇巧淫技”也是可以修改的)。局域网中的路由器/交换机会记录每台计算机的 MAC 地址

MAC 地址是 Media Access Control Address 的缩写,直译为“媒体访问控制地址”,也称为局域网地址(LAN Address),以太网地址(Ethernet Address)或物理地址(Physical Address)。

数据包中除了会附带对方的 IP 地址,还会附带对方的 MAC 地址,当数据包达到局域网以后,路由器/交换机会根据数据包中的 MAC 地址找到对应的计算机,然后把数据包转交给它,这样就完成了数据的传递

 

5、redis通信协议

redis 客户端和服务端之间通信的协议是RESP(REdis Serialization Protocol)。传输层使用TCP。RESP的特点是:

  • 实现容易
  • 解析快
  • 人类可读

5.1、请求格式

*3\r\n
$3\r\n
set\r\n
$4\r\n
name\r\n
$8\r\n
zhangsan\r\n

5.2、响应格式

对于简单字符串,回复的第一个字节是“+”
对于错误,回复的第一个字节是“ - ”
对于整数,回复的第一个字节是“:”
对于批量字符串,回复的第一个字节是“$”
对于数组,回复的第一个字节是“ *”

 

5.3、代码样例

public class RedisSocket {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 6379);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream in = socket.getInputStream();
                    int len = 0;
                    byte[] b = new byte[1024];
                    while((len = in.read(b)) != -1){
                        System.out.println(new String(b,0,len));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();


        OutputStream out = socket.getOutputStream();
        String cmd = "*3\r\n$3\r\nset\r\n$4\r\nbobo\r\n$3\r\nlzz\r\n";
        out.write(cmd.getBytes());
        out.flush();


        System.in.read();
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章