• python network programming--connect()


    首先我们看一段python client/server代码。

    server端:

    >>> import sys,socket
    >>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    >>> MAX = 65535
    >>> PORT = 1060
    >>> s.bind(('127.0.0.1', PORT))
    >>> print 'Listening at', s.getsockname()
    Listening at ('127.0.0.1', 1060)
    >>> while True:
    ...     data, address = s.recvfrom(MAX)
    ...     print 'the client at', address, 'says', repr(data)
    ...     s.sendto('Your data was %d bytes' % len(data), address)

    可以知道server监听在127.0.0.1的1060端口上。当收到 client发来的一段信息之后就会返回给 client一段话.

    再看client端:

    import socket, sys
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    MAX = 65535
    PORT = 1060
    print 'Address before sending:', s.getsockname()
    s.sendto('This is my message', ('127.0.0.1', PORT))
    print 'Address after sending', s.getsockname()
    data, address = s.recvfrom(MAX) # overly promiscuous - see text!
    print 'The server', address, 'says', repr(data)

    客户端非常简单,创建一个socket,通过socket的sendto像server发送一段信息,然后把收到的回复打印出来。

    正常情况下,这两段代码是没什么问题的。可是如果这时候server没有运行,我们的客户端运行之后会怎么样呢? 会 stuck在

    data, address = s.recvfrom(MAX)

    这时候如果你通过一个其它的机器伪造server像client发回复会怎么样呢?我们新开一个窗口输入下面代码来看看

    >>> import sys,socket
    >>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    >>> s.sendto('fake' , ('127.0.0.1',56557))
    4

    注意这里的4是sendto的返回值,表示发送了多长的数据。

    我们看client端

    >>> data, address = s.recvfrom(MAX) # overly promiscuous - see text!
    >>> print 'The server', address, 'says', repr(data)
    The server ('127.0.0.1', 33670) says 'fake'

    client依然把我们伪造的server发回的信息当做server回复处理。  很多时候这是我们不想看到的。 这时候 connect的作用就体现出来了。 通过connect,client将会识别出server的ip和port。如果有数据从其它的ip和port发回,client将不会把它当做server回复。 并且调用了connect之后我们使用的是send()和recv()而不是 sendto()和recvfrom(). 看如下例子:

    >>> import sys ,  socket
    >>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    >>> s.connect(('127.0.0.1',1060))
    >>> print 'Client socket name is', s.getsockname()
    Client socket name is ('127.0.0.1', 48824)
    >>> s.send('This is another message')
    23
    >>> data = s.recv(65535)
    >>> print 'The server says', repr(data)
    The server says 'Your data was 23 bytes'

    这个例子中client调用了connect, 然后用了send 和recv去发收消息。 当发送往正确的server的时候,正常收到了回复。 但是我们看看如果用一个错误的server发送消息给client它还会不会收到呢?

    >>> s.sendto('fake' , ('127.0.0.1',48824))
    4

    在一个新窗口中用socket发送消息到我们 client socket的端口。 但是client端没有反应。

    >>> data = s.recv(65535)

    这是因为 connect 的起到了过滤的作用。 client只会识别connect中提到的server。

    值得了解的是,connect存在的意义不是出于安全考虑。因为connect实际上做的事情是在 OS 的内存中记住了server的地址信息。这样当你调用send 和 recv的时候就不用指定地址了。 调用connect不会在网络上传输数据。 而如果有黑客真的想攻击你,他可以很容易的把自己的地址伪装成server的ip和端口。

    所以如果你的client想要能够识别server和非server, 你可以有两种办法:

    1. 是调用connect。 这种方法非常简单,因connect会在OS的内存中记住server的信息。以后调用send 和 recv实际上都是去查阅这个server信息。 但是这种方法有个不方便的地方就是你一次只能跟一个server对话。如果你想发送给其它的server,需要重新调用connect,但是这样会覆盖之前的connect记住的server信息。

    2. 就是不调用connect,直接使用sendto和recvfrom。在recvfrom之后你可以获得给你发信息的机器的地址信息。你可以写一段代码手动的去比较看是不是真正的服务器。这种方式要手动的写新代码。但是比较灵活,如果你想与多个server通信就不必重复的connect。

    很重要的一点补充。这里的connect是用在UDP上的。而不是TCP。TCP上的connect是真正的网络函数,它会发起TCP三步握手去连接服务器。

  • 相关阅读:
    SpringCloud第五天
    SpringCloud第四天
    SpringCloud第三天
    mysql数据库主从同步I/O问题修复
    linux服务器通过rpm包安装nginx案例
    potplayer最大化不遮挡任务栏
    火狐怎么在新标签打开书签
    Binding failed for port a1e67849-aa1d-418d-a04c-8343b8dbf64f, please check neutron logs for more information
    Unable to mount root fs on unknown-block(0,0)
    安装VCSA6.7
  • 原文地址:https://www.cnblogs.com/kramer/p/3480654.html
Copyright © 2020-2023  润新知