python+pygame实现五子棋网络对战之一

之前我们系统地描述了五子棋的人机对战,了解了五子棋的基本操作,例如电脑的应手算法,输赢判断等等。那如何实现五子棋的网络对战,即人人对战呢?这里就用到了套接字socket编程,听上去很高级,其实无论哪种编程语言,实现起来的方法(套路)都是大同小异的。

一、

python的套接字socket编程基本概念及操作,对基本原理的理解是学习编程的基础。

1.1  服务端就是一系列硬件或软件,为一个或多个客户端(服务端服务的用户)提供所需的“服务”。它存在唯一目的就是等待客户端的请求(经常称之为“监听”),并响应客户端,为客户端提供服务),然后等待更多请求,周而复始。

1.2  套接字是计算机网络数据结构,在任何类型的通信开始之前,网络应用程序必须创建套接字。socket原意就是插座,插口,插孔的意思,所以可以将它们比作网络插孔,没有它将无法进行通信。Python只支持AF_UNIX、AF_NETLINK、AF_TIPC 和 AF_INET ,尤其是使用基于网络的AF_INET.

套接字三要素:IP,端口,协议。python使用元组保存:ADDR = (IP,端口)。协议:

流式套接字(SOCK_STREAM):用于提供面向连接、可靠的数据传输服务。TCP

数据报套接字(SOCK_DGRAM):提供了一种无连接的服务。这个并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。UDP

1.3 python常用对象方法和属性
服务器套接字方法
bind(ADDR)    将地址(主机名、端口号对)绑定到自接字上
listen([backlog])  设置并启动TCP监听器,如果指定backlog,则必须至少为0(如果低于0,则设置为0);
accept()  被动接受TCP客户端连接,一直等待直到连接到达(阻塞)

客户端套接字方法
connect()   主动发起 TCP服务器连接
connect_ex()  connect()的扩展版本,此时会以猎误码的形式返回问题,而不是抛出一个异常

通用套接字方法
recv()  接收 TCP消息
recv_into()  接收TCP 消息到指定的缓冲区
send()   发送TCP消息
sendall()   完整地发送 TCP消息
recvfrom()   接收 UDP消息
recvfrom_into()   接收 UDP 消息到指定的缓冲区
sendto()   发送 UDP消息
getpeername()  连接到套接字(TCP)的远程地址
getsockname()  当前套接字的地址
getsockopt()  返回给定套接字选项的值
setsockopt()  设置给定套接字选项的值
shutdown()   关闭连接
close()    关闭套接字
detach()   在未关闭文件描述符的情况下关闭套接字,返回文件描述符
ioctI()   控制套接字的模式(仅支持Windows)

面向阻塞的套接字方法
setblocking()   设置套接字的阻塞或非阻塞模式
settimeout()   设置阻塞套接字操作的超时时间
gettimeout()   获取阻塞套接字操作的超时时间

面向文件的套接字方法
fileno()   套接字的文件描述符
makefile()   创建与套接字关联的文件对象


数据属性
family   套接字家族,AF_UNIX、AF_NETLINK、AF_TIPC 、AF_INET
type     套接字类型  ,SOCK_STREAM、SOCK_DGRAM
proto    套接字协议

1.4  通常TCP的服务端和客户端创建的步骤如下:

服务端

serverTCP = socket()       		      #  创建服务器套接字
serverTCP.bind(HOST,PORT)       	  #  套接字与地址,端口绑定
serverTCP.listen()         		      #  监听连接
while True:                		      #  服务器无限循环
    clientTCP = serverTCP.accept()    #  接受客户端连接
    comm_loop:          	   		  #  通信循环
        clientTCP.recv()/clientTCP.send() #  对话(接收 / 发送)
    clientTCP.close()                 #  关闭客户端套接字
    serverTCP.close()          		  #  关闭服务器套接字 # (可选)

客户端

clientTCP = socket()        #  创建客户端套接字
clientTCP.connect(HOST,PORT)#  尝试连接服务器
comm_loop:          		#  通信循环
	clientTCP.send()/clientTCP.recv() #  对话(发送 / 接收)
	clientTCP.close()       #  关闭客户端套接字

注:UDP这里不详细讲解。可以参考下面的示例代码:

二、

下面就是详细的python代码。先执行 server.py,然后执行client.py,就可以看到TPC/UDP简单的通信效果了。

server.py

import socket
from time import ctime
import json
import time

HOST = ''
PORT = 9001
ADDR = (HOST, PORT)
BUFFSIZE = 1024
MAX_LISTEN = 5


def tcpServer():
    # TCP服务
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # 绑定服务器地址和端口
        s.bind(ADDR)
        # 启动服务监听
        s.listen(MAX_LISTEN)
        print('等待用户接入......')
        while True:
            # 等待客户端连接请求,获取connSock
            conn, addr = s.accept()
            print('远端客户:{} 接入系统!!!'.format(addr))
            with conn:
                while True:
                    print('接收请求信息......')
                    # 接收请求信息
                    data = conn.recv(BUFFSIZE)
                    print('data=%s' % data)
                    print('接收数据:{%r}'.format(data.decode('utf-8')))

                    # 发送请求数据
                    conn.send(data.encode('utf-8'))
                    print('发送返回完毕!!!')
            s.close()


# 创建UDP服务
def udpServer():
    # 创建UPD服务端套接字
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        # 绑定地址和端口
        s.bind(ADDR)
        # 等待接收信息
        while True:
            print('UDP服务启动,准备接收数据...')
            # 接收数据和客户端请求地址
            data, address = s.recvfrom(BUFFSIZE)

            if not data:
                break

            print('接收请求信息:{}'.format(data.decode('utf-8')))
            s.sendto(b'This is a udp server!', address)

        s.close()

if __name__ == '__main__':
    while True:
        choice = input('请选择 t-tcp 或 u-udp:')

        if choice != 't' and choice != 'u':
            print('请输入 t 或 u,不接受其他字符!')
            continue

        if choice == 't':
            print('TCP服务端')
            tcpServer()
        else:
            print('UDP服务端')
            udpServer()

client.py

import socket

from time import ctime
HOST = 'localhost'
PORT = 9001
ADDR = (HOST, PORT)
ENCODING = 'utf-8'
BUFFSIZE = 1024


def tcpClient():
    # 创建客户套接字
    with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as s:
        # 尝试连接服务器
        s.connect(ADDR)
        print('连接服务成功!!')
        # 通信循环
        while True:
            inData = input('请输入内容(q退出):')
            if inData == 'q':
                break
            # 发送数据到服务器
            inData = '[{}]:{}'.format(ctime(), inData)

            s.send(inData.encode(ENCODING))
            print('发送成功!')

            # 接收返回数据
            outData = s.recv(BUFFSIZE)
            print('返回数据信息:{!r}'.format(outData))

        # 关闭客户端套接字
        s.close()


def udpClient():
    # 创建客户端套接字
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        while True:
            # 发送信息到服务器
            data = input('请输入内容(quit退出):')
            if data == 'quit':
                break
            data = '[{}]:{}'.format(ctime(), data)

            s.sendto(data.encode('utf-8'), ADDR)

            print('send success')

            # 接收服务端返回信息
            recvData, addrs = s.recvfrom(BUFFSIZE)

            print('接收到的信息 : {}'.format(recvData.decode('utf-8')))

        # 关闭套接字
        s.close()


if __name__ == '__main__':

    while True:
        choice = input('请选择 t-tcp  或 u-udp 或 q-quit:')
        if choice == 'q':
            break
        if choice != 't' and choice != 'u':
            print('请输入 t 或 u,不接受其他字符!')
            continue

        if choice == 't':
            print('TCP服务端')
            tcpClient()
        else:
            print('UDP服务端')
            udpClient()

把这两个代码复制,执行一下,看看效果。

待续.....

python+pygame实现五子棋网络对战之二

  • 11
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值