1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > python客户端和服务端区别_Python socket 客户端和服务器端

python客户端和服务端区别_Python socket 客户端和服务器端

时间:2020-12-25 00:29:20

相关推荐

python客户端和服务端区别_Python socket 客户端和服务器端

connection, address = socket.accept()

调 用accept方法时,socket会时入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有两个元素的 元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素 address是客户的Internet地址。

第五步是处理阶段,服务器和客户端通过send和recv方法通信(传输 数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接收信息。调用recv 时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。recv方法在接收数据时会进入“blocked”状态,最后返回一个字符 串,用它表示收到的数据。如果发送的数据量超过了recv所允许的,数据会被截短。多余的数据将缓冲于接收端。以后调用recv时,多余的数据会从缓冲区 删除(以及自上次调用recv以来,客户可能发送的其它任何数据)。

传输结束,服务器调用socket的close方法关闭连接。

python编写client的步骤:

举例:

服务端:

#socket server端

#获取socket构造及常量

from socket import *

#''代表服务器为localhost

myHost = ''

#在一个非保留端口号上进行监听

myPort = 50007

#设置一个TCP socket对象

sockobj = socket(AF_INET, SOCK_STREAM)

#绑定它至端口号

sockobj.bind((myHost, myPort))

#监听,允许5个连结

sockobj.listen(5)

#直到进程结束时才结束循环

while True:

#等待下一个客户端连结

connection, address = sockobj.accept()

#连结是一个新的socket

print 'Server connected by', address

while True:

#读取客户端套接字的下一行

data = connection.recv(1024)

#如果没有数量的话,那么跳出循环

if not data: break

#发送一个回复至客户端

connection.send('Echo=>' + data)

#当socket关闭时eof

connection.close( )

客户端:

import sys

from socket import *

serverHost = 'localhost'

serverPort = 50007

#发送至服务端的默认文本

message = ['Hello network world']

#如果参数大于1的话,连结的服务端为第一个参数

if len(sys.argv) > 1:

serverHost = sys.argv[1]

#如果参数大于2的话,连结的文字为第二个参数

if len(sys.argv) > 2:

message = sys.argv[2:]

#建立一个tcp/ip套接字对象

sockobj = socket(AF_INET, SOCK_STREAM)

#连结至服务器及端口

sockobj.connect((serverHost, serverPort))

for line in message:

#经过套按字发送line至服务端

sockobj.send(line)

#从服务端接收到的数据,上限为1k

data = sockobj.recv(1024)

#确认他是引用的,是'x'

print 'Client received:', repr(data)

#关闭套接字

sockobj.close( )

参考:

/s/blog_523491650100hikg.html

创建一个socket客户端

#coding:utf-8#导入相关模块

importsocketimportsys#设置连接请求30S超时

socket.setdefaulttimeout(30)#IPV4协议、字节流(TCP协议)

try:

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exceptsocket.error as e:print 'Socket Error:%s'%(str(e))

sys.exit()print 'Socket Created!'host= ''port= 80

#获取IP地址

try:

remote_ip= socket.gethostbyname(host) #此处同PHP中的gethostbyname()函数

exceptsocket.gaierror as e:print 'get %s ip error %s'%(host,str(e))

sys.exit()print 'Ip address of %s is %s'%(host,remote_ip)#连接服务器(SOCK_STREAM/TCP 套接字才有“连接”的概念,一些 Socket 如 UDP、ICMP 和 ARP 没有“连接”的概念)

try:

s.connect((remote_ip,port))exceptException as e:print 'Socket Connect to %s:%s Faile!!Error:%s'%(host,port,str(e))

sys.exit()print 'Socket Connect to %s on ip %s'%(host,remote_ip)#发送数据(根据HTTP/1.1协议)#请求消息的结构如下#请求方法 路径 HTTP版本\r\n ------>这为请求行#请求头域1: 请求头域的值1\r\n#请求头域2: 请求头域的值2\r\n#........................ ------->以上行为请求头#一个空行\r\n -------->头与主体间的空行#请求主体...... -------->请求主体#

##########请求行(方法)

msg = "GET / HTTP/1.1\r\n"

#请求header(HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回)

msg+= "Host: \r\n" #空行

msg+= "\r\n"

#请求body(由于我们这里是GET请求所以,body没有)

try:#这里也可用send()方法:不同在于sendall在返回前会尝试发送所有数据

#并且成功时返回是None,而send()则返回发送的字节数量。失败时都抛出异常。

s.sendall(msg)exceptException as e:print 'Send Failed!'sys.exit()print 'Msg Send Successfully!'

#获取服务器返回的数据

respone = s.recv(4096) #这里还可用recvfrom()、recv_into()等等

printrespone#释放资源

s.close()

输出:

Socket created

ip address of is 115.239.210.26

Msg Send successfully!

HTTP/1.1 200 OK

Date: Fri, 21 Feb 05:32:29 GMT

Content-Type: text/html

Transfer-Encoding: chunked

Connection: Keep-Alive

Vary: Accept-Encoding

Set-Cookie: BAIDUID=0D5536687056DF9F5C088AFBE27E42B7:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.

Set-Cookie: BDSVRTM=7; path=/

Set-Cookie: H_PS_PSSID=4850_1432_5186_5198_4261_5260_4760_5208; path=/; domain=.

P3P: CP=" OTI DSP COR IVA OUR IND COM "

Expires: Fri, 21 Feb 05:32:29 GMT

Cache-Control: private

Server: BWS/1.1

BDPAGETYPE: 1

BDQID: 0x95f7c521930a6c8e

BDUSERID: 0

为什么没有输出全部数据呢?看下面的函数:

socket.recv(bufsize[,flags])

Receive data from the socket. The return value is a string representing the data received. The maximum amount of data to be received at once is specified bybufsize. See the Unix manual pagerecv(2)for the meaning of the optional argumentflags; it defaults to zero.

Note

For best match with hardware and network realities, the value ofbufsizeshould be a relatively small power of 2,for example, 4096.

输出不完整。一些数据被漏掉。在TCP/IP协议下上面的情况会发生。在这个协议,数据以块进行传输。例如一个网页是500kb,但是最大快只有64kb。因此传输网页时,一次只传输了一部分而不是全部。

这就是问题产生的原因。recv函数能够等待直到收到所有的数据,但是对此,它必须知道整个要传输数据的大小。s.recv(4096 , socket.MSG_WAITALL) 会等待直到得到整个4096 bytes。现在如果实际响应的大小小于这个尺寸,函数会被阻塞一段时间,直到它返回。这不是我们所期待的。

解决:

解决方法是保持查询数据直到一个适当的超时发生,下面的例子中,我们就是这么做的:

def recv_timeout(the_socket,timeout=2):#make socket non blocking

the_socket.setblocking(0)#total data partwise in an array

total_data=[];

data='';#beginning time

begin=time.time()while 1:#if you got some data, then break after timeout

if total_data and time.time()-begin >timeout:break

#if you got no data at all, wait a little longer, twice the timeout

elif time.time()-begin > timeout*2:break

#recv something

try:

data= the_socket.recv(8192)ifdata:

total_data.append(data)#change the beginning time for measurement

begin=time.time()else:#sleep for sometime to indicate a gap

time.sleep(0.1)except:pass

#join all parts to make final string

return ''.join(total_data)

步骤是:

1.保证socket非阻塞。对此,socket不会等待,如果在recv调用没有数据。它会继续,如果没有数据可用。

2.按下面方式循环:保持调用recv,直到一个超时发生或recv完成。

现在这是一个简单的方法来证明recv函数在实际的应用中该如何工作。同样的函数能够进一步开发,然后变得更复杂,根据工作的协议,例如HTTP。

创建一个socket服务器端

#coding:utf-8

importsocketimportsysimporttimeimportQueueimportthreading

host= 'localhost'port= 8000

#创建socket对象

s =socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定一个特定地址,端口

try:

s.bind((host,port))exceptException as e :print 'Bind Failed:%s'%(str(e))

sys.exit()print 'Socket bind complete!!'

#监听连接

s.listen(10) #最大连接数10

#创建连接队列

queue =Queue.Queue()#创建线程

classTaskThread(threading.Thread):def __init__(self):

threading.Thread.__init__(self)defrun(self):while 1:

t=queue.get()

t.send('welecome.....')#接收数据

client_data = t.recv(1024)

t.sendall(client_data)#释放资源

#t.close()

#接受连接

while 1:#将连接放入队列

conn,addr =s.accept()print 'Connected from %s:%s'%(addr[0],str(addr[1]))

queue.put(conn)#生成线程池

th =TaskThread()

th.setDaemon(True)

th.start()

queue.join()

s.close()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。