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三步握手去连接服务器。

  • 相关阅读:
    我为能准时下班而做的准备,以及由此的收获,同时总结下不足
    用象棋的思维趣说IT人的职业发展和钱途
    简历上如果出现过于高大上的项目,反而过犹不及:再论如何通过项目引出技术
    用python的matplotlib和numpy库绘制股票K线均线的整合效果(含从网络接口爬取数据和验证交易策略代码)
    如果当前没有拿得出手的简历,也别慌,努力的话最多两年情况就能改变
    分析若干没面试机会和没体现实力的简历
    IT人为了自己父母和家庭,更得注意自己的身体和心理健康
    Spring Cloud系列文,Feign整合Ribbon和Hysrix
    以互联网公司的经验告诉大家,架构师究竟比高级开发厉害在哪?
    博客园是个大金矿,管理员不挖掘有些可惜:给博客园提一些双赢的建议
  • 原文地址:https://www.cnblogs.com/kramer/p/3480654.html
Copyright © 2011-2022 走看看