一、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()