C++ 通过套接字发送数据不需要';行不通

C++ 通过套接字发送数据不需要';行不通,c++,sockets,networking,network-programming,client-server,C++,Sockets,Networking,Network Programming,Client Server,我想通过插座做一盘国际象棋。 有一个服务器负责将棋盘发送给玩家,以获取输入和响应等。。 我试图创建一个客户机-服务器(实际上是2个客户机和服务器),但它不起作用。 客户端正确地连接到服务器,但发送的数据不正确。 例如,我从客户端发送“E2-C3”;recv结果(在服务器端)始终为0,或者打印垃圾 客户: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <

我想通过插座做一盘国际象棋。 有一个服务器负责将棋盘发送给玩家,以获取输入和响应等。。 我试图创建一个客户机-服务器(实际上是2个客户机和服务器),但它不起作用。 客户端正确地连接到服务器,但发送的数据不正确。 例如,我从客户端发送“E2-C3”;recv结果(在服务器端)始终为0,或者打印垃圾

客户:

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sys/types.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

using namespace std;


#define SERVER_IP "1.1.1.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

// server side 
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30

// client side
#define MOVE 10

int __cdecl main()
{
    WSADATA info;
    int errorDATA; // configuriation 
    int socketCreate; // create the socket - empty
    SOCKADDR_IN ClientService; // configuriation (stage 3) - data of the server.
    int connectResult;
    char sendBuf[1024], recvbuf[1024];
    int iResult;

    /*Configuration*/
    errorDATA = WSAStartup(MAKEWORD(2, 2), &info);
    if (errorDATA == INVALID_SOCKET)
    {
        printf("WSAStartup failed with error : %d\n", errorDATA);
        return -1;
    }
    /*Create empty socket*/
    socketCreate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // creating the socket "Clean - empty"
    if (socketCreate == INVALID_SOCKET)
    {
        printf("Error number %d in creating socket!\n", WSAGetLastError());
        return -1;
    }
    printf("Creating socket SUCCEEDED!\n");

    /*Confugirate the created socket*/
    ClientService.sin_family = AF_INET;
    ClientService.sin_addr.s_addr = inet_addr(SERVER_IP); // server's ip
    ClientService.sin_port = htons(SERVER_PORT);

    /*Asking for connection*/
    connectResult = connect(socketCreate, (struct sockaddr*) &ClientService, sizeof(ClientService));

    while (1)
    {
        cout << "Please enter a move : " << endl;
        cin >> sendBuf;
        iResult = send(socketCreate, sendBuf, (int)strlen(sendBuf), 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(socketCreate);
            WSACleanup();
            return 1;
        }
        // MOVE 
        iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
        if (iResult > 0)
        {
            if (recvbuf[0] == '0' && recvbuf[1] == '0')
            {
                cout << "You've entered an illegal move. Please try again." << endl;
                continue;
            }
            else if (recvbuf[0] == '2' && recvbuf[1] == '0')
            {
                // print the board.
                bool keepGoing = 0;
                do
                {
                    iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
                    if (iResult > 0)
                    {
                        if (recvbuf[0] == '1' && recvbuf[1] == '5')
                        {
                            keepGoing = true;
                            continue;
                        }
                    }
                } while (!keepGoing);
            }
        }
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
    }


    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(socketCreate, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(socketCreate);
        WSACleanup();
        return 1;
    }


    // cleanup
    closesocket(socketCreate);
    WSACleanup();

    cin.get();
    system("pause");
    return 0;
}
#定义WIN32_LEAN_和_MEAN
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//需要链接到Ws2_32.lib、Mswsock.lib和Advapi32.lib
#pragma注释(lib,“Ws2_32.lib”)
#pragma注释(lib,“Mswsock.lib”)
#pragma注释(lib,“AdvApi32.lib”)
使用名称空间std;
#定义服务器IP“1.1.1.1”
#定义服务器\u端口8888
#定义缓冲区大小1024
//服务器端
#定义无效的\u MOVE 00
#定义请输入移动15
#定义打印板20
#定义第30场比赛的结束
//客户端
#定义移动10
int_u_CDECLmain()
{
WSADATA信息;
int errorDATA;//配置
int socketCreate;//创建套接字-空
ClientService中的SOCKADDR_;//配置(阶段3)-服务器的数据。
int连接结果;
char sendBuf[1024],recvbuf[1024];
国际结果;
/*配置*/
errorDATA=WSAStartup(MAKEWORD(2,2),&info);
if(errorDATA==无效的\u套接字)
{
printf(“WSAStartup失败,错误:%d\n”,errorDATA);
返回-1;
}
/*创建空套接字*/
socketCreate=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建套接字“Clean-empty”
if(socketCreate==无效的_套接字)
{
printf(“创建套接字时出现错误号%d!\n”,WSAGetLastError());
返回-1;
}
printf(“创建套接字成功!\n”);
/*对创建的套接字进行加密*/
ClientService.sin_family=AF_INET;
ClientService.sin_addr.s_addr=inet_addr(服务器IP);//服务器的IP
ClientService.sin_-port=htons(服务器_-port);
/*请求联系*/
connectResult=connect(socketCreate,(struct sockaddr*)&ClientService,sizeof(ClientService));
而(1)
{
库特森布夫;
iResult=send(socketCreate,sendBuf,(int)strlen(sendBuf),0);
if(iResult==SOCKET\u错误){
printf(“发送失败,错误:%d\n”,WSAGetLastError());
closesocket(socketCreate);
WSACleanup();
返回1;
}
//移动
iResult=recv(socketCreate,recvbuf,strlen(recvbuf),0);
如果(iResult>0)
{
if(recvbuf[0]='0'&&recvbuf[1]='0')
{
问题是

strlen(recvbuf)
你可能是说

sizeof(recvbuf)
strlen(recvbuf)在您收到数据之前没有意义,因为您的缓冲区只包含垃圾,因此strlen()只是一个坏的随机数生成器。strlen(recvbuf)在收到数据后,如果您确定数据中已填充0,则有意义。如果不是这样,您可以使用的返回值来确定收到的字节数。

问题在于

strlen(recvbuf)
你可能是说

sizeof(recvbuf)

strlen(recvbuf)在您收到数据之前没有意义,因为您的缓冲区只包含垃圾,因此strlen()只是一个坏的随机数生成器。strlen(recvbuf)在收到数据后,如果您确定数据中填充了0,则有意义。如果不是这样,您可以使用的返回值来确定收到的字节数。

Hans说了什么。另外:

int in = recv(clientsock[0], client1_buffer, 0, 0);
你可能想说:

int in = recv(clientsock[0], client1_buffer, BUFFER_SIZE, 0);
此外,您还犯了许多人使用套接字时都会犯的一个基本错误。您假设服务器上的
recv
调用返回的字节数与客户端传递给相应的
send
调用的字节数相同。碎片、分段和其他网络内容可能会导致您只接收部分字节数在另一个节点的
send
调用上发送的消息(因此,TCP是一种流协议)


您应该认真检查
recv
的返回值。编写代码时,就好像发件人一次只发送1个字节一样。您应该在消息之间放置分隔符(空字符可以)然后在recv上循环,直到收到完整的消息。否则,在您自己的PC和本地子网上运行正常的系统在部署到internet时会出现奇怪的错误。

Hans说的话。另外:

int in = recv(clientsock[0], client1_buffer, 0, 0);
你可能想说:

int in = recv(clientsock[0], client1_buffer, BUFFER_SIZE, 0);
此外,您还犯了许多人使用套接字时都会犯的一个基本错误。您假设服务器上的
recv
调用返回的字节数与客户端传递给相应的
send
调用的字节数相同。碎片、分段和其他网络内容可能会导致您只接收部分字节数在另一个节点的
send
调用上发送的消息(因此,TCP是一种流协议)


您应该认真检查
recv
的返回值。编写代码时,就好像发件人一次只发送1个字节一样。您应该在消息之间放置分隔符(空字符可以)并在recv上循环,直到收到完整的消息。否则,在您自己的PC和本地子网上运行正常的程序在部署到internet时将出现奇怪的错误。

服务器文件中的更改

int in = recv(clientsock[0], client1_buffer, 0,0);

int in = recv(clientsock[0], client1_buffer, 1024,0);

change是服务器文件更改中要接收的日期的长度

int in = recv(clientsock[0], client1_buffer, 0,0);

int in = recv(clientsock[0], client1_buffer, 1024,0);

更改是要接收的日期的长度

谢谢!我遇到的另一个问题是服务器等待消息而没有收到消息时打印0。如何修复它?对于初学者,您启用了非阻塞模式:
ioctlsocket(serverSocket、FIONBIO和iMode);
Take