zoukankan      html  css  js  c++  java
  • 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三步握手去连接服务器。

  • 相关阅读:
    DAY9学习笔记
    DAY8课下作业
    DAY8学习笔记
    DAY7课下作业
    github clone 开源代码报Permission denied (publickey)
    grandle构建工程报:javax.net.ssl.SSLException
    centos安装redash
    centos安装nodejs
    CURL执行请求
    flume定制拦截器Interceptor
  • 原文地址:https://www.cnblogs.com/kramer/p/3480654.html
Copyright © 2011-2022 走看看