Python 网络编程, socket

百度百科上介绍说:Socket原意是 “插座”,可以看成是在两个程序进行通讯连接中的端点,是连接应用程序和网络驱动程序的桥梁。Socket在应用程序中创建,通过绑定与网络驱动建立关系。套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。

        个人的理解:假设有一个有两个门的房间,这两个门都有各自的钥匙,且一个是面向服务器(server)的,另一个是面向客户(client)的,当服务器与客户分别拿到这两把钥匙时,二者就可以通过这个房间交换信息了。这对钥匙就相当于是一对socket,网络通路相当于是房间,但因为网络通路并不是只有一条,相当于存在无数个这样的房子,所以就有无数对这样的钥匙,这时每个socket应该有些信息来标注自己的身份,不然分不清了,与人们一般选择不同形状的钥匙一个道理。具体实现中socket使用了三种手段一起来为自己标注:一种是网络传输协议的种类(TCP or UDP),然后是对方的IP地址,最后是对方(客户端)或自己(服务器端)的端口号Port. 一旦服务器端与客户端的socket能配对上,则二者就可以通信了。

        这里简单说下TCP与UDP。TCP即传输控制协议(Transmission Control Protocol),是一种流套接字,是面向连接的,在通信之前,要建立并维持一条连接,直到通信结束,这种方式叫做“虚电路”,是一种可靠数据传输方式,通过握手机制保证数据传输的准确性。UDP即用户数据报协议(User Datagram Protocol),不需要在通信前提前建立一条连接,而在确定了合适大小的报文大小后,直接把数据放到网上,通过路由控制协议向目的地传输,不保证数据传输的正确性与顺序,速度比TCP快好多,广泛应用于视频音频等即时通信服务中。

        Python中使用socket模块进行client/server 网络编程。基于网络的socket有一个自己的address family name: AF_INET. socket模块可以选择TCP/UDP,目的地地址与端口,并有相关数据传输与接收函数。

实例:

由于是在同一台电脑上运行,所以开了两个Python: Python3.3(for server), Python3.2(for client)

TCP-服务器端:

[python]  view plain copy
  1. from socket import*  
  2. from time import ctime  
  3.   
  4. HOST='' #空表示可以接收多有有效ip地址的连接请求,bind()函数可以绑定在所有有效的ip地址上  
  5. PORT=8080 #随机选的一个端口号,必须大于1024  
  6. BUFSIZ=1024 #每次读取的数据量  
  7. ADDR=(HOST,PORT) #HOST与PORT共同组成了ADDR  
  8.   
  9. tcpSerSock=socket(AF_INET, SOCK_STREAM) #创建了一个基于网络的、使用TCP的socket。AF_INET表示是基于网络的socket编程,SOCK_STREAM表示是TCP通信  
  10. tcpSerSock.bind(ADDR) #socket与ADDR绑定到一起,表示socket可以在这个PORT上接收HOST处的连接请求。还需要开始监听  
  11. tcpSerSock.listen(5#开始监听,5表示同时最多可以有5个连接进来。开始等待连接到来  
  12.   
  13. while True#表示一直等待  
  14.     print("waiting for connecting...")  
  15.     (tcpCliSock,addr)=tcpSerSock.accept() #如果有连接进来,则生成一个新的socket: tcpCliSock,并得到源的地址  
  16.     print('...connected from: ',addr)  
  17.   
  18.     while True#开始接收数据,并处理  
  19.         data=tcpCliSock.recv(BUFSIZ).decode('utf8'#接收数据,并转化成utf-8格式,原始的是bytes格式  
  20.         if not data: #如果没有数据了,则跳出while循环,等待下一次连接到来  
  21.             break;  
  22.         print('[%s] %s'%(ctime(),data)) #向shell输出,增加了当前的时间  
  23.         tcpCliSock.send(('[%s] %s'%(ctime(),data)).encode('utf8')) #将数据转换成bytes型,再send回去  
  24.   
  25.     tcpCliSock.close() #关闭tcpCliSock,一次通信在服务器端的工作完成,继续等待下一次连接的到来  
  26. tcpSerSock.close() #不会被执行到,可以加个try-except进去,让程序更友好  

TCP-客户端:

[python]  view plain copy
  1. from socket import*  
  2.   
  3. HOST='localhost' #由于是在同一台电脑上,所以可以写localhost,如果是在两台电脑上,则这儿要写server的ip地址  
  4. PORT=8080  
  5. BUFSIZ=1024  
  6. ADDR=(HOST,PORT) #服务器的ADDR  
  7.   
  8. tcpCliSock=socket(AF_INET,SOCK_STREAM)  
  9. tcpCliSock.connect(ADDR) #连接到服务器,成功后,服务器端输出'...coonnected from...'  
  10.   
  11. while True:  
  12.     data=input('> ').encode('utf8')  
  13.     if not data: #直接敲回车,则跳出while循环  
  14.         break;  
  15.     tcpCliSock.send(data)   
  16.     data=tcpCliSock.recv(BUFSIZ)   
  17.     if not data:  
  18.         break;  
  19.     print(data.decode('utf8'))  
  20. tcpCliSock.close()  


        服务器端将bytes格式转换成utf-8格式,而客户端不需要的原因是,客户端没有对数据进行处理,直接输出;而服务器端在原数据基础上增加了当前的时间,所以转换成uft-8格式,便于处理。utf-8是unicode,可以处理汉语。

TCP-通信结果:

[python]  view plain copy
  1. >>>   
  2. waiting for connecting... #先运行服务器,等待客户端的运行  
  3. ...connected from:  ('127.0.0.1'53808#当客户端运行,则出现这一行,同时客户端出现'> '  
  4. [Wed Aug 14 20:50:19 2013] Python编程 #输出处理后的结果  
  5. waiting for connecting... #一轮通信完成,等待下一轮的到来  
  6.   
  7. >>>   
  8. > Python编程 #向服务器端发送数据:'Python编程'  
  9. [Wed Aug 14 20:50:19 2013] Python编程 #得到服务器端的反馈  
  10. >  #结束  
  11. >>>   

UDP-服务器端:(与TCP大同小异)

[python]  view plain copy
  1. from socket import *  
  2. from time import ctime  
  3.   
  4. HOST=''  
  5. PORT=8080  
  6. BUFSIZ=1024  
  7. ADDR=(HOST,PORT)  
  8.   
  9. udpSerSock=socket(AF_INET,SOCK_DGRAM) #SOCK_DGRAM表示是UDP通信  
  10. udpSerSock.bind(ADDR) #绑定到ADDR,由于没有'虚电路',无连接,所以不需要listen,只是被动等待数据到来  
  11.   
  12. while True#被动等待数据到来  
  13.     print('waiting for message...')  
  14.     (data,addr)=udpSerSock.recvfrom(BUFSIZ) #当有数据到来时,得到data与源addr。注意这里不能产生一个新的socket,因为UDP是无连接的  
  15.     data=data.decode('utf8'#bytes转换成utf-8  
  16.     udpSerSock.sendto(('[%s] %s'%(ctime(),data)).encode('utf8'),addr) #传输处理后的数据,需要写addr,仍然因为是无连接  
  17.     print('...received from and returned to:',addr)  
  18.   
  19. udpSerSock.close()  

UDP-客户端:

[python]  view plain copy
  1. from socket import*  
  2.   
  3. HOST='localhost'  
  4. PORT=8080  
  5. BUFSIZ=1024  
  6. ADDR=(HOST,PORT)  
  7.   
  8. udpCliSock=socket(AF_INET,SOCK_DGRAM) #SOCK_DGRAM表示UDP通信  
  9.   
  10. while True:  
  11.     data=input('> ').encode('utf8')  
  12.     if not data:  
  13.         break;  
  14.     udpCliSock.sendto(data,ADDR)  
  15.     (data,ADDR)=udpCliSock.recvfrom(BUFSIZ) #可以得到ADDR  
  16.     if not data:  
  17.         break;  
  18.     print(data.decode('utf8'))  
  19.   
  20. udpCliSock.close()  

UDP-通信结果:

[python]  view plain copy
  1. >>>   
  2. waiting for message...  
  3. ...received from and returned to: ('127.0.0.1'56259)  
  4. waiting for message...  
  5.   
  6. >>>   
  7. > Python编程  
  8. [Wed Aug 14 20:53:39 2013] Python编程  
  9. >   
  10. >>>   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值