百度百科上介绍说: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. #如果有连接进来,则生成一个新的socket: tcpCliSock,并得到源的地址  
16. print('...connected from: ',addr)  
17.   
18. while True: #开始接收数据,并处理  
19. 'utf8') #接收数据,并转化成utf-8格式,原始的是bytes格式  
20. if not data: #如果没有数据了,则跳出while循环,等待下一次连接到来  
21. break;  
22. print('[%s] %s'%(ctime(),data)) #向shell输出,增加了当前的时间  
23. '[%s] %s'%(ctime(),data)).encode('utf8')) #将数据转换成bytes型,再send回去  
24.   
25. #关闭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. '> ').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。注意这里不能产生一个新的socket,因为UDP是无连接的  
15. 'utf8') #bytes转换成utf-8  
16. '[%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. '> ').encode('utf8')  
    12. if not data:  
    13. break;  
    14.     udpCliSock.sendto(data,ADDR)  
    15. #可以得到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. >>>