基于TCP的socket编程实现猜数字游戏(服务端和客户端分离)

猜数字游戏要求:
当客户端第一次连上服务器时,服务器产生一个[0,50]的随机数。
客户端从键盘输入一个数字(猜),将其发送给服务器。
服务器判断客户端发来的数字是否刚才产生的数字,然后返回“大”或“小”的比较结果。
客户端根据返回的评判结果继续猜(输入数字),再发选给服务器。
客户端一共有5次猜的机会,若猜中,则服务器返回“SUCCESS!”然后开启再玩一局或者退出。若猜不中,服务器返回“Falledl”然后开启再玩一局或退出。
若退出,服务器和客户端都结束程序。

介绍该版本适用于Windows版本,如果想在Linux中实现应该在顶端添加该代码行:

#include "stdafx.h"  

服务器端代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

int main(int argc, char* argv[])
{
// 初始化WSA
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
// 创建套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
    printf("socket error !");
    return 0;
}

// 绑定IP和端口
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(slisten, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
{
    printf("bind error !");
    return 0;
}

// 开始监听
if (listen(slisten, 5) == SOCKET_ERROR)
{
    printf("listen error !");
    return 0;
}

// 产生随机数
srand((unsigned int)time(NULL));
int num = rand() % 51;

// 循环接收数据
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char recvData[255];
int guessNum, guessCount = 0;
bool success = false;
while (true)
{
    // 等待连接
    printf("等待连接...\n");
    sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
    if (sClient == INVALID_SOCKET)
    {
        printf("accept error !");
        continue;
    }
    printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));

    // 开始猜数字
    while (!success && guessCount < 5)
    {
        // 接收猜测数字
        int ret = recv(sClient, recvData, 255, 0);
        if (ret <= 0)
        {
            break;
        }
        recvData[ret] = '\0';
        guessNum = atoi(recvData);
        printf("收到猜测数字:%d\n", guessNum);

        // 判断猜测结果
        guessCount++;
        if (guessNum == num)
        {
            char *successMsg = "SUCCESS!\n";
            send(sClient, successMsg, strlen(successMsg), 0);
            success = true;
            break;
        }
        else if (guessNum > num)
        {
            char *greaterMsg = "大\n";
            send(sClient, greaterMsg, strlen(greaterMsg), 0);
        }
        else
        {
            char *lessMsg = "小\n";
            send(sClient, lessMsg, strlen(lessMsg), 0);
        }
    }

    // 发送最终结果
    if (success)
    {
        printf("猜测成功!\n");
    }
    else
    {
        printf("猜测失败!\n");
}
const char *finalMsg = success ? "再玩一局(Y/N)?\n" : "很遗憾,再玩一局(Y/N)?\n";
send(sClient, finalMsg, strlen(finalMsg), 0);
// 等待玩家选择是否再玩一局
int ret = recv(sClient, recvData, 255, 0);
if (ret <= 0)
{
    break;
}
recvData[ret] = '\0';
if (recvData[0] == 'N' || recvData[0] == 'n')
{
    break;
}
else
{
    // 重置游戏
    num = rand() % 51;
    guessCount = 0;
    success = false;
}
}

// 关闭套接字和WSA
closesocket(sClient);
closesocket(slisten);
WSACleanup();

return 0;
}

客户端代码:

#include <WINSOCK2.H>
#include <STDIO.H>

#pragma  comment(lib,"ws2_32.lib")


int main(int argc, char* argv[])
{
    WORD sockVersion = MAKEWORD(2,2);
    WSADATA data;
    if(WSAStartup(sockVersion, &data) != 0)
    {
        return 0;
    }

    SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sclient == INVALID_SOCKET)
    {
        printf("invalid socket !");
        return 0;
    }

    sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(8888);
    serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//记得根据ipconfig所显示的ipv4
//进行修改
    if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
    {
        printf("connect error !");
        closesocket(sclient);
        return 0;
    }
    char * sendData = "你好,TCP服务端,我是客户端!\n";
    send(sclient, sendData, strlen(sendData), 0);
//先发后收
    char recData[255];
    int ret = recv(sclient, recData, 255, 0);
    if(ret > 0)
    {
        recData[ret] = 0x00;
        printf(recData);
    }
    closesocket(sclient);
    WSACleanup();
    return 0;
}

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值