|
目录一、关于socket的介绍二、创建套接字对象(Socket的实例化)三、套接字对象方法(Socket常用函数)1、bind函数2、listen函数3、accept函数4、connect与connect_ex函数5、send、 sendall、sendto函数6、recv与 recvfrom函数7、close函数三、简单的服务端和客户端示例四、关于socket库相关方法函数的总结一、关于socket的介绍Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。python中提供了两个基本的Socket模块:服务端Socket和客户端Socket,当创建了一个服务端Socket 后,这个Socket就会在本机的一个端口上等待连接,当客户端Socket访问这个端口,两者完成连接后就能够进行交互了。二、创建套接字对象(Socket的实例化)在使用Socket进行编程时,需要先实例化一个Scoket类,Python中,我们用socket()函数来创建套接字。关于socket函数的用法:scoket(family,type[,protocol])第一个参数family是指定应用程序使用的通信协议的协议族,有:Family参数描述socket.AF_UNIX只能够用于单一的Unix系统进程间通信socket.AF_INET服务器之间网络通信socket.AF_INET6IPv6默认值为AF_INET第二个参数type为要创建套接字的类型Type参数描述socket.SOCK_STREAM流式socket,当使用TCP时选择此参数socket.SOCK_DGRAM数据报式socket,当使用UDP时选择此参数socket.SOCK_RAW原始套接字,允许对底层协议如IP、ICMP进行直接访问第三个参数protocol是可选项,指明所要接收的协议类型,通常为0或者不填。Type参数描述socket.IPPROTO_RAW相当于protocol=255,此时socket只能用来发送IP包,而不能接收任何的数据。发送的数据需要自己填充IP包头,并且自己计算校验和。socket.IPPROTO_IP相当于protocol=0,此时用于接收任何的IP数据包。其中的校验和和协议分析由程序自己完成。接下来我们实例化一个简单的TCP类型的Socket测试代码:importsockets=socket.socket(socket.AF_INET,socket.SOCK_STREAM)print(s)print(type(s))代码解释:首先肯定需要使用import导入socket库;用一个自定义参数(我这里用的s)来接收创建的套接字对象;输出套接字对象以及它的类型。运行结果:关于运行结果的解释:fd=332:表示套接字的文件描述符(filedescriptor),在此处为332。family=2:表示套接字的地址族(addressfamily),这里是IPv4地址族(AF_INET)。type=1:表示套接字的类型(sockettype),这里是流式套接字(SOCK_STREAM),用于TCP协议。proto=0:表示套接字使用的协议,这里是默认协议(通常与套接字类型相关)。:表示所创建的对象属于Python的socket模块中的socket类。三、套接字对象方法(Socket常用函数)首先介绍服务端函数1、bind函数该函数是服务端函数,会将之前创建的套接字与指定的IP地址和端口进行绑定,使用点直接调用该方法,以元组(host,port)的形式表示地址。比如我们绑定本地的12345端口:s.bind(('127.0.0.1',12345))注意这里用到了两次括号,因为bind方法的参数需要是一个包含主机地址和端口号的元组。2、listen函数该函数也是服务端函数,用于在使用TCP的服务端开启监听模式,只有一个参数,指定在拒绝连接之前,操作系统可以挂起的最大连接数量,该值至少为1,大部分应用程序设为5即可。在服务端开启监听,设置操作系统可以挂起的最大连接数量为5:s.listen(5)listen()只是让套接字处于监听状态,并没有接收请求,接收请求需要使用accept()函数。 3、accept函数当套接字处于监听状态时,可以通过accept()函数来接收客户端请求,该函数也是服务端函数,接受TCP连接并返回(conn,address),返回一个新的套接字来和客户端通信,其中conn是新的套接字对象,可以用来接收和发送数据,address是连接客户端的地址。比如我们就使用conn和address这两个参数(可自定义)来接收accept函数返回的值conn,address=s.accept()下面介绍客户端函数4、connect与connect_ex函数connect()是客户端程序用来连接服务端的方法,客户端连接到address处的套接字,一般address的格式为元组(host,port),如果连接出错,会返回socket.error错误。比如我们连接到刚才创建的套接字,即本地的12345端口:importsocketc=socket.socket()c.connect(('127.0.0.1',12345))只有经过connect连接成功后的套接字对象才能调用发送和接受方法(send/recv),所以服务端的s对象不能send或者 recv。还有一个connect_ex函数,功能与connect相同,只是成功返回0,失败返回error的值。下面是一些常见的公共函数5、send、 sendall、sendto函数send():用于发送TCP数据用法:s.send(string[,flag])将string中的数据发送到连接的套接字,返回值是要发送的字节数量,该数量可能小于string的字节大小。sendall():完整发送TCP数据用法:s.sendall(string[,flag])与send()类似,将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据,成功返回None,失败则抛出异常。关于参数的说明:string:这是要发送的数据,通常是一个字符串。这是必需的参数。flag:这是一个可选的参数,用于指定发送数据的附加选项,在大多数情况下可以省略。比如我们将"Hello,server!"字符串通过UTF-8编码转换为字节数据,然后使用套接字的send方法发送这些字节数据到连接的服务端:c.send("Hello,server!".encode('utf-8'))sendto:用于发送UDP数据用法:s.sendto(string[,flag],address) 将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址,返回值是发送的字节数。6、recv与 recvfrom函数recv:接受TCP套接字的数据,数据以字符串形式返回。用法:s.recv(bufsize[,flag])参数说明:bufsize:这是一个整数,表示要接收的最大字节数。接收的实际数据可能少于或等于这个值,取决于发送端发送的数据量。flag(可选):这是一个可选的参数,用于指定接收数据的附加选项。在大多数情况下,可以省略这个参数。通过recv方法接收最多1024字节的数据,我们将接收到的字节数据解码为UTF-8编码的字符串,最后打印出来:re=c.recv(1024)print(re.decode('utf-8'))recvfrom:接受UDP套接字的数据,与recv()类似,但返回值是(data,address)。其中data包含接收数据的字符串,address是发送数据的套接字地址。特别说明:recvfrom函数是可以在没有进行connect的情况下使用的,对于UDP套接字,可以在未连接的状态下使用recvfrom来接收数据。recvfrom通常与UDP一起使用,因为UDP是一个无连接协议,而recvfrom提供了从发送端获取地址信息的能力。在TCP中,由于是面向连接的,地址信息通常在连接建立时就已经确定了,所以recv通常就足够了。示例:importsocket#创建一个UDP套接字s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#绑定本地地址和端口s.bind(('127.0.0.1',12345))#接收数据,设置bufsize为最大接收字节数data,address=s.recvfrom(1024)#打印接收到的数据和发送端地址信息print(f"Receiveddata:{data.decode('utf-8')}")print(f"Receivedfrom:{address}")7、close函数该函数用于关闭套接字直接使用点调用即可s.close()三、简单的服务端和客户端示例服务端代码:importsocket#创建一个TCP套接字server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定主机和端口server_socket.bind(('127.0.0.1',12345))#监听连接server_socket.listen()print("Serverislisteningforincomingconnections...")#接受客户端连接client_socket,client_address=server_socket.accept()print(f"Connectionestablishedwith{client_address}")#接收数据data=client_socket.recv(1024)print(f"Receiveddata:{data.decode('utf-8')}")#发送响应response="Hello,client!"client_socket.send(response.encode('utf-8'))#关闭连接client_socket.close()server_socket.close() 客户端代码:importsocket#创建一个TCP套接字client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#连接到服务器client_socket.connect(('127.0.0.1',12345))#发送数据data_to_send="Hello,server!"client_socket.send(data_to_send.encode('utf-8'))#接收响应response=client_socket.recv(1024)print(f"Receivedresponse:{response.decode('utf-8')}")#关闭连接client_socket.close()先开启服务端,再运行客户端运行效果:四、关于socket库相关方法函数的总结Socket创建和配置:socket(family,type,proto=0,fileno=None):创建一个套接字对象。gethostname():获取主机名。 通用套接字方法:bind(address):将套接字绑定到指定的地址。listen(backlog):开始监听传入连接请求。accept():接受连接,返回新的套接字和对端地址。connect(address):连接到远程套接字。close():关闭套接字。数据收发:send(bytes):发送数据。recv(bufsize):接收数据。UDP相关方法:sendto(data,address):发送UDP数据到指定地址。recvfrom(bufsize):接收UDP数据和对端地址。设置和获取套接字选项:setsockopt(level,optname,value):设置套接字选项。getsockopt(level,optname,buflen=None):获取套接字选项。获取主机信息:gethostbyname(hostname):通过主机名获取IP地址。gethostbyaddr(ip_address):通过IP地址获取主机名。
|
|