一、TCP SERVER
#!/usr/bin/env python
#-*- coding:utf-8 -*-


"""
对于服务器,建立TCP通信需要4步:
1.建立socket对象
2.设置socket选项(可选的)
3.绑定到一个端口(同样,也可以是一个指定的网卡)
4.侦听连接
"""

"""
    import socket
    host = ''
    port = 51423


    # 1.建立socket对象
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 2.
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    # 3.
    s.bind((host,port))
    # 4.
    s.listen(5)
"""

# s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 对于socket.SO_REUSEADDR。通常地,在一个服务器进程终止后,操作系统会保留几分钟它的端口,从而防止其他进程(甚至包括本服务器自己的另外一个实例)在超时之前使用这个端口。
# 如果设置socket.SO_REUSEADDR的标记为true(布尔型整数),操作系统就会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口。这样做使调式程序更简单。
# SO_REUSEADDR选项设置如下:
# s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# python 定义setsockopt()和getsockopt()
# setsockopt(level,optname,value)
# getsockopt(level,optname[,buflen])
# SOL_SOCKET 意思是,正在用到socket选项

# 查看socket可用的选项列表
"""
    import socket
    soList = [x for x in dir(socket) if x.startswith('SO_')]
    soList.sort()
    for x in soList:
        print x
"""

# 通常使服务器连续运行的办法是小心设计一个无限循环
import socket
import traceback

host = ''
port = 51423

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
print 'Waiting for connections...'
s.listen(1)

while 1:
    try:
        clientsock,clientaddr = s.accept()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()
        continue

    # Process the connection
    try:
        print 'Got connection from',clientsock.getpeername() # 打印客户端的ip和端口号
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()

    # Close the connection
    try:
        clientsock.close()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()

# 通常情况下,无限循环是不好的,因为它们会耗尽系统的CPU资源。然而,这里的循环是不同的:当调用accept()的时候,它只会在一个客户端连接后才返回。
# 同时,程序停止,并不使用任何的CPU资源
# 一个停止并等待输入或输出的程序称为阻塞的程序


二、TCP Client
#!/usr/bin/env python
#-*- coding:utf-8 -*-

import socket

host = 'localhost'
port = 51423

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
data = 'hello'
s.send(data)
print s.getsockname()
s.close()
三、UDP server
#!/usr/bin/env python
#-*- coding:utf-8 -*-

# 从客户端角度来看,使用UDP比TCP要困难,因为客户端必须注意丢失信息包的问题。
# 从服务端来看,UDP则要容易得多。程序员在编写UDP服务器的时候,不用考虑丢失信息包的问题。
# 如果客户端来的信息包一直没有到达的话,UDP服务器根本就不会知道有客户端曾经试图发送过请求。
# 由于几乎所有的UDP通信都会包括客户端发送一个简短的请求,以及服务器发送一个简短的应答,
# 所以服务器是没有办法察觉和解决丢失信息包的问题的
# 还是应该由客户端担负起这个责任。

"""
    import socket
    import traceback

    host = ''
    port =51423

    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    s.bind((host,port))

    while 1:
        try:
            message,address = s.recvfrom(8192)
            print 'Got data from',address
            print 'Message:\n',message
            if 'Bye' in message:
                s.sendto('Bye',address)
                continue
            #s.sendto(message,address)
            data = 'hello udpclient'
            s.sendto(data,address)

        except (KeyboardInterrupt,SystemExit):
            raise
        except:
            traceback.print_exc()
"""


# UDP服务器 返回昨天的日期

import socket,traceback,time,struct

host = ''
port = 51422

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))

while 1:
    try:
        message,address = s.recvfrom(8192)
        print 'Message from client: ',message
        secs = int(time.time())     # seconds since 1/1/1970
        secs -= 60*60*24            # make it yesterday
        secs += 2208988800          # convert to secs since 1/1/1900
        reply = struct.pack('!I',secs)
        s.sendto(reply,address)
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()
四、UDP client
#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    import socket

    host = 'localhost'
    port = 51423

    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    s.connect((host,port))
    data = 'hello udpserver'
    s.send(data)
    while 1:

        buf = s.recv(1024)
        if 'Bye' in buf:
            print buf
            break
        if len(buf) == 15:
            s.send('Bye-Bye')
        print buf
    s.close()
"""

# 访问时间服务器

import socket,time,struct,sys

host = 'localhost'
port = 51422

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#s.connect((host, port))
data = 'Get me time! ..I am udpclient'
s.sendto(data,(host, port))

print 'Looking for replies; press Ctrl-C to stop.'
buf = s.recv(2048)
if len(buf) != 4:
    print "Wrong-sized reply %d: %s" % (len(buf),buf)
    sys.exit(1)

secs = struct.unpack('!I',buf)[0]
secs -= 2208988800
print time.ctime(int(secs))


s.close()