《Python网络编程》Part1 Socket、IPv4和简单的客户端/服务器编程
2016-11-17 16:32
537 查看
《Python网络编程》Part1 Socket、IPv4和简单的客户端/服务器编程
1、获取主机名和IP地址
.py:
2、获取远程设备的IP地址
.py:
3、将IPv4地址转换成不同的格式
定义convert_ip4_address()函数,调用inet_aton()和inet_ntoa()转换IP地址。
4、通过制定的端口和协议找到服务名
如果想找到网络服务,最好知道该服务运行在TCP或UDP协议的哪个端口上。
使用for—in语句比那里一组变量。在每次遍历中,获取端口对应的服务名。
.py:
5、主机字节序和网络字节序之间相互转换
编写底层网络应用是,或许需要处理通过电缆在两台设备之间传送的底层数据。在这种操作中,需要把主机操作系统发出的数据转换成网络格式,或者做你想转换,因为这两种数据的表示方式不一样。
Python的socket库提供了将数据在网路字节序和主机字节序之间相互转换的函数,例如ntohl()和htonl(),ntohs()和htons()。
.py:
6、设定并获取默认的套接字超时时间
有时需要处理socket库某些属性的默认值,例如套接字超时时间。
.py:
7、优雅地处理套接字错误
在网络中经常会遇到这种情况:一方尝试连接,但另一方由于网络媒介失效或者其他原因无法响应。Python的socket库提供了一个方法,能通过socket.error异常优雅地处理套接字错误。
8、修改套接字发送和接收的缓冲区大小
很多时候,默认的套接字缓冲大小可能不够用。此时,可以将默认的套接字缓冲区大小改成一个更合适的值。
在套接字对象上可调用方法getsockopt()he setsockopt()分别获取和修改套接字对象的属性。setsockopt()方法接收三个参数:level、opename和value。其中,optname是选项名,value是该选项的值。第一个参数所用的符号变量是(SO_*等)可在socket模块中查看。
.py:
9、把套接字改成阻塞或费阻塞模式
默认情况下,TCP套接字处于阻塞模式中。也就是说,除非完成了某项操作,否则不会把控制权交还给程序。例如,调用connect()API后,链接操作会组织程序继续往下执行,直到链接成功为止。很多情况下,你并不想让程序一直等待服务器响应或者有异常终止操作。例如,如果编写了一个网页浏览器客户端链接服务器,你应该考虑提供取消功能,以便在操作过程中取消连接。这是就要把套接字设置成非阻塞模式。
在Python中,套接字可以被设置为阻塞模式或者非阻塞模式。在非阻塞模式中,调用API后,例如send()或recv()方法,如果遇到问题就会跑出异常。但在阻塞模式中,遇到错误并不会阻止操作。我们可以创建一个普通的TCP套接字,分别在阻塞模式和非阻塞模式中执行操作实验。
为了能在阻塞模式中处理套截止,首先要创建一个套接字对象。然后调用setblocking(1)把套接字设为阻塞模式,或者调用setblocking(0)把套接字设为非阻塞模式。最后,吧套接字绑定到指定的端口上,监听进入的链接。
.py:
将s.setblocking(1)改为s.setblocking(0),即由阻塞模式改为非阻塞模式,运行:
10、重用套接字地址
不管链接是被有意还是无意关闭,有时你想时钟在同一个端口上运行套接字服务器。某些情况下,如果客户端程序需要一直链接指定的服务器端口,这么做就很有用,因为无需改变服务器端口。
创建套接字对象之后,我们可以查询地址重用的状态,比如说旧状态。然后,调用setsocketopt()方法,修改地址重用状态的值。再按照常规的步骤,把套接字绑定到一个地址上,监听进入的客户端链接。在这个例子中,我们要捕获KeyboardInterrupt异常,这样按下Ctrl+C键后,Python脚本会终止运行,但不会显示任何异常消息。
.py:
可以在一个终端窗口运行这个脚本,然后在另一个终端窗口中输入telnet localhost 8282,尝试连接这个服务器。关闭服务器后,还可以使用同一个端口再次连接。然而,如果你把设定SO_REUSEADDR的那行代码注释掉,服务器将不会再次运行脚本。
11、从网络时间服务器获取并打印当前时间
很多程序要求设备的时间精准,例如Unix系统中的make命令。设备上的时间可能不都准确,需要和网络中的时间服务器同步。
你可以编写一个python客户端,让设备上的时间和某个网络时间服务器同步。要完成这一操作,需要使用ntplib,通过“网络时间协议”(Network Time Protocol,简称NTP)处理客户端和服务器之间的通信。如果设备中没有安装ntplib,可以使用pip或easy_install从PyPI中安装,命令如下:
$pip install ntplib
如果是Windows系统,到官方网站上,https://pypi.python.org/pypi/ntplib,下载ntplib-0.3.3.tar.gz ,然后解压,将ntplib.py拷贝到D:\Python27\Lib(这是我的路径,自己的安装路径自己注意),这就解决了,为啥Linux的包解压的文件能在Windows里用,这个我就不解释了。
.py:
12、编写一个SNTP客户端
与上一个程序不同,有时并不需要从NTP服务器上获取精确的时间。遇到这种情况,就可以使用NTP的简化版本,叫作“简单网络时间协议(SNTP)”
不使用任何第三方库来编写一个简单的SNTP客户端。
首先定义两个常量:NTP_SERVER和TIME1970。NTP_SERVER是客户端要链接的服务器地址,TIME1970是指1970年1月1日(也叫Epoch)。在http://www.epochconverter.com/上可以查看Epoch时间值,或者把时间转换成Epoch时间值。这个客户端通过UDP协议创建一个UDP套接字(SOCK_DGRAM),用于连接服务器。然后,客户端要在一个数据包中把数据'\x1b'
+ 47 * '\0'发送给SNTP服务器。UDP客户端分别使用sendto()和recvfrom()方法发送和接收数据。
服务器返回的时间信息打包在一个数组中,客户端需要使用struct模块取出数据。我们所需的数据是数组中的第11个元素。最后,我们要从取出的数据上减掉TIME1970,得到真正的当前时间。
这个SNTP客户端创建一个套接字连接,然后通过协议发送数据。从NTP服务器(这里使用的是0.uk.pool.ntp.org)收到数据后,使用struct模块取出数据。最后,减去1970年1月1日对应的时间截,再使用Python内置的time模块提供的ctime()方法打印时间。
.py:
13、编写一个简单的回显客户端/服务器应用
尝试过Python中socket模块的基本API后,现在来编写一个套接字服务器和客户端。这里,你将有机会利用在签署攻略中掌握的基本知识。
不管服务器从客户端收到什么输入,都会将其回显来。我们要使用Python中的argparse模块,在命令行中指定TCP端口。服务器脚本和客户端脚本都要用到这个参数。
先写一个服务器。首先创建一个TCP套接字对象。然后设定启用重用地址,这样想运行多少次服务器就能运行多少次。我们把套接字绑定在本地设备的指定端口上。在监听阶段,把backlog参数传入listen()方法中,让服务器在队列中监听多个客户端。最后,等待客户端连接,向服务器发送一些数据。收到数据后,服务器会把数据回显给客户端。
echo_server.py:
Python的语法格式一定要多加注意,否则一直编译出错。
客户端中,我们创建一个客户端套接字,然后使用命令行参数中指定的端口链接服务器。客户端把消息Test message. This will be echoed发送给服务器后,立即就会在几个数据片段中收到返回的消息。这里用到了两个try-except块,捕获交互过程中发生的任何异常。
echo_client.py:
3、重复步骤1,键入echo_client.py --port=9900
然后服务器端窗口显示如下:
4、修改接收的消息长度,将客户端的data = sock.recv(16)修改为32:
重复上述步骤:
1、获取主机名和IP地址
.py:
import socket def print_machine_info(): host_name = socket.gethostname() ip_address= socket.gethostbyname(host_name) print "Host name: %s" % host_name print "IP address: %s" % ip_address if __name__ == '__main__': print_machine_info()
2、获取远程设备的IP地址
.py:
import socket def get_remote_machine_info(): remote_host = 'www.python.org' try: print "IP address: %s" %socket.gethostbyname(remote_host) except socket.error, err_msg: print "%s: %s" %(remote_host,err_msg) if __name__ == '__main__': get_remote_machine_info()
3、将IPv4地址转换成不同的格式
定义convert_ip4_address()函数,调用inet_aton()和inet_ntoa()转换IP地址。
import socket from binascii import hexlify def convert_ip4_address(): for ip_addr in ['127.0.0.1','192.168.0.1']: packed_ip_addr = socket.inet_aton(ip_addr) unpacked_ip_addr = socket.inet_ntoa(packed_ip_addr) print "IP Adress: %s => Packed: %s, Unpacked: %s"\ %(ip_addr,hexlify(packed_ip_addr),unpacked_ip_addr) if __name__ == '__main__': convert_ip4_address()
4、通过制定的端口和协议找到服务名
如果想找到网络服务,最好知道该服务运行在TCP或UDP协议的哪个端口上。
使用for—in语句比那里一组变量。在每次遍历中,获取端口对应的服务名。
.py:
import socket def find_service_name(): protocolname = 'tcp' for port in [80,25]: print "Port: %s => service name: %s" %(port, socket.getservbyport(port,protocolname)) print "Port: %s => service name: %s" %(53,socket.getservbyport(53,'udp')) if __name__ == '__main__': find_service_name()
5、主机字节序和网络字节序之间相互转换
编写底层网络应用是,或许需要处理通过电缆在两台设备之间传送的底层数据。在这种操作中,需要把主机操作系统发出的数据转换成网络格式,或者做你想转换,因为这两种数据的表示方式不一样。
Python的socket库提供了将数据在网路字节序和主机字节序之间相互转换的函数,例如ntohl()和htonl(),ntohs()和htons()。
.py:
import socket def convert_integer(): data = 1234 # 32-bit print "Original: %s => Long host byte order: %s,Network byte order: %s"\ %(data,socket.ntohl(data),socket.htonl(data)) # 16-bit print "Original: %s => Short host byte order: %s,Network byte order: %s"\ %(data,socket.ntohs(data),socket.htons(data)) if __name__ == '__main__': convert_integer()以整数为例,演示了如何把它转换成网络自己序和主机字节序。socket库中的类函数ntohl()把网络自己序转换成长整形主机字节序。函数名中的n表示网络;h表示主机;l表示长整形;s表示短整形,即16位。
6、设定并获取默认的套接字超时时间
有时需要处理socket库某些属性的默认值,例如套接字超时时间。
.py:
import socket def test_socket_timeout(): s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) print "Default socket timeout: %s" %s.gettimeout() s.settimeout(100) print "Current socket timeout: %s" %s.gettimeout() if __name__ == '__main__': test_socket_timeout()首先创建一个套接字对象。套接字构造方法的第一个参数是地址簇,第二个参数是套接字类型。然后,调用gettimeout()方法获取套接字超时时间,再调用settimeout()方法修改超时时间。传给settimeout()方法的参数可以是秒数(非浮点数)也可以是None。这个方法在处理阻塞式套接字操作时使用。如果把超时时间设为None,则禁用了套接字操作的超时检测。
7、优雅地处理套接字错误
在网络中经常会遇到这种情况:一方尝试连接,但另一方由于网络媒介失效或者其他原因无法响应。Python的socket库提供了一个方法,能通过socket.error异常优雅地处理套接字错误。
import socket import sys import argparse def main(): #setup argument parsing parser = argparse.ArgumentParser(description = 'Socket Error Examples') parser.add_argument('--host',action="store",dest="host",required=False) parser.add_argument('--port',action="store",dest="port",type=int,required=False) parser.add_argument('--file',action="store",dest="file",required=False) given_args = parser.parse_args() host = given_args.host port = given_args.port filename = given_args.file #First try-except block -- creat socket try: s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) except socket.error, e: print "Error creating socket: %s" %e sys.exit(1) #Second try-except block -- connect to given host/port try: s.connect((host, port)) except socket.gaierror, e: print "Address-related error connecting to server: %s" % e sys.exit(1) except socket.error, e: print "Connect error: %s" %e sys.exit(1) #Third try-except block -- sending data try: s.sendall("GET %s HTTP/1.0\r\n\r\n" %filename) except socket.error, e: print "Error sending data: %s" %e sys.exit(1) while 1: #Forth try-except block -- waiting to recieve data from remote host try: buf = s.recv(2048) except socket.error, e: print "Error receiving data: %s" %e sys.exit(1) if not len(buf): break; #write the recieved data sys.stdout.write(buf) if __name__ == '__main__': main()
8、修改套接字发送和接收的缓冲区大小
很多时候,默认的套接字缓冲大小可能不够用。此时,可以将默认的套接字缓冲区大小改成一个更合适的值。
在套接字对象上可调用方法getsockopt()he setsockopt()分别获取和修改套接字对象的属性。setsockopt()方法接收三个参数:level、opename和value。其中,optname是选项名,value是该选项的值。第一个参数所用的符号变量是(SO_*等)可在socket模块中查看。
.py:
import socket SEND_BUF_SIZE = 4096 RECV_BUF_SIZE = 4096 def modify_buf_size(): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Get the size of the socket's send buffer bufsize = sock.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) print "Buffer size [Before]:%d" %bufsize sock.setsockopt(socket.SOL_TCP,socket.TCP_NODELAY,1) sock.setsockopt( socket.SOL_SOCKET, socket.SO_SNDBUF, SEND_BUF_SIZE) sock.setsockopt( socket.SOL_SOCKET, socket.SO_RCVBUF, RECV_BUF_SIZE) bufsize =sock.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) print "Buffer size [After]:%d" %bufsize if __name__ == '__main__': modify_buf_size()
9、把套接字改成阻塞或费阻塞模式
默认情况下,TCP套接字处于阻塞模式中。也就是说,除非完成了某项操作,否则不会把控制权交还给程序。例如,调用connect()API后,链接操作会组织程序继续往下执行,直到链接成功为止。很多情况下,你并不想让程序一直等待服务器响应或者有异常终止操作。例如,如果编写了一个网页浏览器客户端链接服务器,你应该考虑提供取消功能,以便在操作过程中取消连接。这是就要把套接字设置成非阻塞模式。
在Python中,套接字可以被设置为阻塞模式或者非阻塞模式。在非阻塞模式中,调用API后,例如send()或recv()方法,如果遇到问题就会跑出异常。但在阻塞模式中,遇到错误并不会阻止操作。我们可以创建一个普通的TCP套接字,分别在阻塞模式和非阻塞模式中执行操作实验。
为了能在阻塞模式中处理套截止,首先要创建一个套接字对象。然后调用setblocking(1)把套接字设为阻塞模式,或者调用setblocking(0)把套接字设为非阻塞模式。最后,吧套接字绑定到指定的端口上,监听进入的链接。
.py:
import socket SEND_BUF_SIZE = 4096 RECV_BUF_SIZE = 4096 def test_socket_modes(): s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #blocking mode s.setblocking(1) s.settimeout(0.5) s.bind(("127.0.0.1",0)) socket_address = s.getsockname() print "Trivial Server launched on socket: %s" %str(socket_address) while(1): s.listen(1) if __name__ == '__main__': test_socket_modes()
将s.setblocking(1)改为s.setblocking(0),即由阻塞模式改为非阻塞模式,运行:
10、重用套接字地址
不管链接是被有意还是无意关闭,有时你想时钟在同一个端口上运行套接字服务器。某些情况下,如果客户端程序需要一直链接指定的服务器端口,这么做就很有用,因为无需改变服务器端口。
创建套接字对象之后,我们可以查询地址重用的状态,比如说旧状态。然后,调用setsocketopt()方法,修改地址重用状态的值。再按照常规的步骤,把套接字绑定到一个地址上,监听进入的客户端链接。在这个例子中,我们要捕获KeyboardInterrupt异常,这样按下Ctrl+C键后,Python脚本会终止运行,但不会显示任何异常消息。
.py:
import socket import sys def reuse_socket_addr(): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Get the old state of the SO_REUSEADDR option old_state = sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) print "Old sock state: %s" %old_state #Enable the SO_REUSEADDR option sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) new_state =sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) print "New sock state: %s" %new_state local_port = 8282 srv = socket.socket(socket.AF_INET,socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) srv.bind( ('', local_port) ) srv.listen(1) print "Listen on port: %s" %local_port while True: try: connection, addr =srv.accept() print 'Connected by %s' %(addr[0], addr[1]) except KeyboardInterrupt: break except socket.error, msg: print '%s' % (msg,) if __name__ == '__main__': reuse_socket_addr()
可以在一个终端窗口运行这个脚本,然后在另一个终端窗口中输入telnet localhost 8282,尝试连接这个服务器。关闭服务器后,还可以使用同一个端口再次连接。然而,如果你把设定SO_REUSEADDR的那行代码注释掉,服务器将不会再次运行脚本。
11、从网络时间服务器获取并打印当前时间
很多程序要求设备的时间精准,例如Unix系统中的make命令。设备上的时间可能不都准确,需要和网络中的时间服务器同步。
你可以编写一个python客户端,让设备上的时间和某个网络时间服务器同步。要完成这一操作,需要使用ntplib,通过“网络时间协议”(Network Time Protocol,简称NTP)处理客户端和服务器之间的通信。如果设备中没有安装ntplib,可以使用pip或easy_install从PyPI中安装,命令如下:
$pip install ntplib
如果是Windows系统,到官方网站上,https://pypi.python.org/pypi/ntplib,下载ntplib-0.3.3.tar.gz ,然后解压,将ntplib.py拷贝到D:\Python27\Lib(这是我的路径,自己的安装路径自己注意),这就解决了,为啥Linux的包解压的文件能在Windows里用,这个我就不解释了。
.py:
import ntplib from time import ctime def print_time(): ntp_client = ntplib.NTPClient() response = ntp_client.request('pool.ntp.org') print ctime(response.tx_time) if __name__ == '__main__': print_time()
12、编写一个SNTP客户端
与上一个程序不同,有时并不需要从NTP服务器上获取精确的时间。遇到这种情况,就可以使用NTP的简化版本,叫作“简单网络时间协议(SNTP)”
不使用任何第三方库来编写一个简单的SNTP客户端。
首先定义两个常量:NTP_SERVER和TIME1970。NTP_SERVER是客户端要链接的服务器地址,TIME1970是指1970年1月1日(也叫Epoch)。在http://www.epochconverter.com/上可以查看Epoch时间值,或者把时间转换成Epoch时间值。这个客户端通过UDP协议创建一个UDP套接字(SOCK_DGRAM),用于连接服务器。然后,客户端要在一个数据包中把数据'\x1b'
+ 47 * '\0'发送给SNTP服务器。UDP客户端分别使用sendto()和recvfrom()方法发送和接收数据。
服务器返回的时间信息打包在一个数组中,客户端需要使用struct模块取出数据。我们所需的数据是数组中的第11个元素。最后,我们要从取出的数据上减掉TIME1970,得到真正的当前时间。
这个SNTP客户端创建一个套接字连接,然后通过协议发送数据。从NTP服务器(这里使用的是0.uk.pool.ntp.org)收到数据后,使用struct模块取出数据。最后,减去1970年1月1日对应的时间截,再使用Python内置的time模块提供的ctime()方法打印时间。
.py:
import socket import struct import sys import time NTP_SERVER = "0.uk.pool.ntp.org" TIME1970 = 2208988800L def sntp_client(): client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) data ='\x1b' + 47 * '\0' client.sendto(data,(NTP_SERVER,123)) data, address = client.recvfrom(1024) if data: print 'Response receiveed from:', address t=struct.unpack('!12I', data)[10] t -= TIME1970 print '\tTime = %s' %time.ctime(t) if __name__ == '__main__': sntp_client()
13、编写一个简单的回显客户端/服务器应用
尝试过Python中socket模块的基本API后,现在来编写一个套接字服务器和客户端。这里,你将有机会利用在签署攻略中掌握的基本知识。
不管服务器从客户端收到什么输入,都会将其回显来。我们要使用Python中的argparse模块,在命令行中指定TCP端口。服务器脚本和客户端脚本都要用到这个参数。
先写一个服务器。首先创建一个TCP套接字对象。然后设定启用重用地址,这样想运行多少次服务器就能运行多少次。我们把套接字绑定在本地设备的指定端口上。在监听阶段,把backlog参数传入listen()方法中,让服务器在队列中监听多个客户端。最后,等待客户端连接,向服务器发送一些数据。收到数据后,服务器会把数据回显给客户端。
echo_server.py:
import socket import sys import argparse host = 'localhost' data_payload = 2048 backlog = 5 def echo_server(port): """A simple echo server""" #create a TCP socket sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Enable reuse address/port sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #bind the socket to the port server_address = (host,port) """Pay attention to " %s port %s",or it will trow exceptions""" print "Starting up echo server on %s port %s" %server_address sock.bind(server_address) #Listen to clients, backlog argument specifies the max no. of queued connections sock.listen(backlog) while True: print "Waiting to receive message from client " client,address = sock.accept() data = client.recv(data_payload) if data: print "Data: %s" %data client.send(data) print "sent %s bytes back to %s" %(data,address) #end connection client.close() if __name__ == '__main__': parser = argparse.ArgumentParser(description = 'Socket Server Example') """Pay attention to tab position ,or it will throw exceptions!!!""" parser.add_argument('--port',action="store",dest="port",type=int, required=True) given_args = parser.parse_args() port = given_args.port echo_server(port)
Python的语法格式一定要多加注意,否则一直编译出错。
客户端中,我们创建一个客户端套接字,然后使用命令行参数中指定的端口链接服务器。客户端把消息Test message. This will be echoed发送给服务器后,立即就会在几个数据片段中收到返回的消息。这里用到了两个try-except块,捕获交互过程中发生的任何异常。
echo_client.py:
import socket import sys import argparse host = 'localhost' def echo_client(port): """A simple echo client""" #create a TCP/IP socket sock =socket.socket(socket.AF_INET,socket.SOCK_STREAM) #connect the socket to the server server_address = (host,port) print "connecting to %s port %s" %server_address sock.connect(server_address) #send data try: #Send data message = "Test message. This will be echoed" print "Sending %s " %message sock.sendall(message) #Look for the response amount_received = 0 amount_expected = len(message) while amount_received < amount_expected: data = sock.recv(16) amount_received += len(data) print "Received: %s" %data except socket.errno, e: print "Socket error: %s" %str(e) except Exception, e: print "Other exception: %s" %str(e) finally: print "Closing connection to the server" sock.close() if __name__ == '__main__': parser = argparse.ArgumentParser(description='Socket Server Example') parser.add_argument('--port',action="store",dest="port",type=int, required=True) given_args = parser.parse_args() port = given_args.port echo_client(port)
3、重复步骤1,键入echo_client.py --port=9900
然后服务器端窗口显示如下:
4、修改接收的消息长度,将客户端的data = sock.recv(16)修改为32:
重复上述步骤:
相关文章推荐
- android的Socket编程---实现简单的服务器,并与客户端通信
- Python的套接字、IPv4和简单的客户端/服务器编程
- socket编程之简单的服务器与客户端
- 简单的TCP协议 socket编程(C语言版服务器和客户端)
- 运用Java中socket编程实现简单的服务器客户端收发信息程序
- 【网络编程笔记】简单的TCP协议 socket编程(C语言版服务器和客户端)
- Linux socket编程-最简单的服务器和客户端程序
- 套接字、IPv4和简单的客户端/服务器编程
- 简单的TCP协议 socket编程(C语言版服务器和客户端)
- socket编程:服务器与客户端简单交互的例子
- Android中socket编程实现简单的客户端和服务器之间的通信
- TCP/TP编程 - 一个简单的Linux下C写的socket服务器客户端程序
- Linux socket编程-最简单的服务器和客户端程序
- socket编程(一),实现服务器与客户端简单通信
- socket编程:简单TCP服务器/客户端编程
- linux socket 编程一:简单的服务器和客户端通信
- socket编程:简单UDP服务器/客户端编程
- socket编程:简单UDP服务器/客户端编程
- 网络编程:使用Socket实现简单的服务器和客户端的通信
- socket编程:简单TCP服务器/客户端编程