Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 发送:尝试发送数据时,非套接字上的套接字操作和segfault错误_C++_Sockets_Networking - Fatal编程技术网

C++ 发送:尝试发送数据时,非套接字上的套接字操作和segfault错误

C++ 发送:尝试发送数据时,非套接字上的套接字操作和segfault错误,c++,sockets,networking,C++,Sockets,Networking,我正在执行一个刽子手游戏,并试图向服务器发送一些数据。 当我通过VS代码和终端运行它时,这段代码在我的mac电脑上编译并运行良好,但在学校用来评分的网络上却不起作用 当我在那里运行它时,在我输入一个玩家的名字后,它会自动停止。我试图修复它,但它要么出错,要么给我一个“发送:非套接字上的套接字操作”错误 以下是完整的代码: 客户端代码: #include <sys/socket.h> #include <netinet/in.h> #include <sys/type

我正在执行一个刽子手游戏,并试图向服务器发送一些数据。 当我通过VS代码和终端运行它时,这段代码在我的mac电脑上编译并运行良好,但在学校用来评分的网络上却不起作用

当我在那里运行它时,在我输入一个玩家的名字后,它会自动停止。我试图修复它,但它要么出错,要么给我一个“发送:非套接字上的套接字操作”错误

以下是完整的代码:

客户端代码:

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <arpa/inet.h>
#include <cstring>
#include <algorithm>

void printDashed(std::string dashed);
int main(int argc, char *argv[]) {

    // check for correct number of arguments
    if (argc != 3) {
        std::cout << "Invalid argument..." << std::endl;
        return -1;
    }

    // store arguments 
    char *ipAddress = argv[1];
    char *port = argv[2];

    // check if port number argument valid
    for (int i = 0; i < strlen(port); i++) {
        if (isdigit(port[i] == 0)) {
            perror("invalid port number");
            return -1;
        }
    }

    // convert from string to int 
    int portNumber = atoi(port);

    int clientSocket;
    struct sockaddr_in address;

    // convert address
    if ((inet_pton(AF_INET, ipAddress, &address.sin_addr)) != 1){
        perror("inet_pton");
        return -1;
    }

    int conn;

    //////////////////////// CREATE CLIENT SOCKET //////////////////////////////
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == -1) {
        perror("Cannot open the socket...");
        return -1;
    }
    address.sin_family = AF_INET;
    address.sin_port = htons(portNumber);

    /////////////////////// CONNECT ////////////////////////////////////////////
    conn = connect(clientSocket, (struct sockaddr* ) &address, sizeof(address));
    if (conn < 0) {
        perror("cannot connect");
        return -1;
    }

    ///////////////////////////// start game ///////////////////////////////////
    std::string player;
    std::cout << "\nWelcome to hangman game! \n";
    std::cout << "Please, Enter your name: ";
    std::cin >> player;
    std::cout << std::endl;

    // recieve the number of letters in the word
    int wordLength;
    if (recv(clientSocket, (void*) &wordLength, sizeof(wordLength), 0) < 0){
        perror("recv");
        return -1;
    }
    //htonl(wordLength);

    // send the name to the server
    if (send(clientSocket, (void *) &player, sizeof(player), 0) < 0){
        perror("send");
        return -1;
    }

    char guess;
    bool correct;
    int numGuess;
    int numCorrect = 0;
    bool notWon = true;
    std::string dashed;
    char *buffer = new char[1000];


    int turn = 0;
    while (notWon) {

        turn++;
        if (recv(clientSocket, (void*) &dashed, sizeof(dashed), 0) < 0){
            perror("recv");
            return -1;
        }
        std::cout << "Turn " << turn << std::endl;
        std::cout << "Word: ";
        printDashed(dashed);
        std::cout << std::endl;

        // ask the user for a guess
        std::cout << "Guess a letter: " << std::endl;
        std::cin >> guess;

        // check the input for validity
        while (isdigit(guess) || islower(guess)) {
            std::cout << "You entered an invalid character!\nPlease enter a valid guess: ";
            std::cin >> guess;
        }
        // send the guess to the server
        if (send(clientSocket, (void*) &guess, sizeof(guess), 0) < 0) {
            perror("send");
            return -1;
        }

        // recive the guess response fromt he server
        if (recv(clientSocket, (void*) &correct, sizeof(correct),0) < 0) {
            perror("recv");
            return -1;
        }
        if (recv(clientSocket, (void*) &dashed, sizeof(dashed),0) < 0){
            perror("recv");
            return -1;
        }
        if (recv(clientSocket, (void*) &numGuess, sizeof(numGuess),0) < 0){
            perror("recv");
            return -1;
        }
        if (recv(clientSocket, (void*) &numCorrect, sizeof(numCorrect),0) < 0){
            perror("recv");
            return -1;
        }

        if (!correct){
            std::cout << "Incorrect guess!" << std::endl;
        } else {
            std::cout << "Correct guess!" << std::endl;
        }
        std::cout << std::endl;

        if (numCorrect == wordLength){
            std::cout << "Congratulations! You guessed the word ";
            printDashed(dashed);
            std::cout << "!\n";
            std::cout << "It took " << turn << " turns to guess the word correctly." << std::endl;
            std::cout << std::endl;

            notWon = false;
        }
        if (send(clientSocket, (void*) &notWon, sizeof(notWon), 0) < 0){
            perror("send");
            return -1;
        }
    }

    std::cout << "LEADER BOARD" << std::endl;
    recv(clientSocket, buffer, 1000, 0);
    std::cout << buffer << std::endl;
    std::cout << std::endl;
}

void printDashed(std::string dashed) {
    for(int i = 0; i < dashed.length(); i++) {
        std::cout << dashed[i];
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效打印虚线(标准::字符串虚线);
int main(int argc,char*argv[]){
//检查参数数量是否正确
如果(argc!=3){

std::cout我在您的代码中看到了许多问题

最大的问题之一是您没有正确地读取/发送
std::string
对象

send(…,&string,sizeof(string),…)

recv(…,&string,sizeof(string),…)

std::string
对象上

对于
send()
,您需要

send(…,string.c_str(),string.length(),…)

对于
recv()
,它更复杂一些。您需要类似以下内容:

size = ...;
string.resize(size);
recv(..., &string[0], size, ...);
这意味着在读取数据之前要知道要发送的
大小
。因此,在发送数据之前,需要发送字符串的实际
长度

您需要定义一个协议,即一组规则,准确地描述客户机和服务器应该如何相互通信,它们应该如何格式化来回的数据,等等

我在代码中看到的其他问题包括:

  • 未正确地将客户端信息传递给
    pthread\u create()

  • 在赢得游戏后处理排行榜时未正确解锁互斥锁

  • 很明显,您正在使用C++11或更高版本(因为您使用了
    std::to_string()
    ),但您没有使用任何C++11功能,例如
    std::thread
    std:mutex
    而不是
    pthread\u create
    p\u thread\u mutex
    ,RAII用于清理,
    auto
    ,基于范围的
    用于
    循环,

话虽如此,请尝试以下方式:

MY_COMMON_代码。H:

\ifndef MY_COMMON_code\H
#定义我的\u通用\u代码\u H
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
void throwRuntimeError(const char*msg,int err);
void throwRuntimeError(const char*msg);
void sendRaw(int sock,const void*数据,size\u t size);
void readRaw(int sock、void*数据、大小);
void sendChar(int sock,char值);
char readChar(int sock);
void sendBool(int sock,bool值);
bool readBool(int sock);
void sendInt32(int sock,int32_t值);
int32_t readInt32(intsock);
void sendString(int sock、const std::string和value);
std::string readString(intsock);
结构套接字删除器{
typedef int指针;
void操作符()(int sock)常量{if(sock!=-1)close(sock);}
};
使用socket\u ptr=std::unique\u ptr;
#恩迪夫
MY_COMMON_CODE.CPP:

#include <sstream>
#include <stdexcept>

#include "my_common_code.h"

void throwRuntimeError(const char *msg, int err)
{
    std::ostringstream oss;
    if (msg && *msg) oss << msg << ": ";
    oss << strerror(err);
    throw std::runtime_error(oss.str());
}

void throwRuntimeError(const char *msg)
{
    std::ostringstream oss;
    if (msg && *msg) oss << msg;
    throw std::runtime_error(oss.str());
}

void sendRaw(int sock, const void *data, size_t size)
{
    const char *pdata = static_cast<const char *>(data);
    while (size > 0) {
        ssize_t sent = send(sock, pdata, size, 0);
        if (sent < 0)
            throwRuntimeError("send", errno);
        pdata += sent;
        size -= sent;
    }
}

void readRaw(int sock, void *data, size_t size)
{
    char *pdata = static_cast<char *>(data);
    while (size > 0) {
        ssize_t recvd = recv(sock, pdata, size, 0);
        if (recvd < 0)
            throwRuntimeError("recv", errno);
        if (recvd == 0)
            throwRuntimeError("disconnected");
        pdata += sent;
        size -= sent;
    }
    return true;
}

void sendChar(int sock, char value)
{
    sendRaw(sock, &value, sizeof(value));
}

char readChar(int sock)
{
    char value;
    readRaw(sock, &value, sizeof(value));
    return value;
}

void sendBool(int sock, bool value)
{
    sendRaw(sock, &value, sizeof(value));
}

bool readBool(int sock)
{
    bool value;
    readRaw(sock, &value, sizeof(value));
    return value;
}

void sendInt32(int sock, int32_t value)
{
    value = htonl(value);
    sendRaw(sock, &value, sizeof(value));
}

int32_t readInt32(int sock)
{
    int32_t value;
    readRaw(sock, &value, sizeof(value));
    return ntohl(value);
}

void sendString(int sock, const std::string &value)
{
    int32_t size = value.length();
    sendInt32(sock, size);
    sendRaw(sock, s.c_str(), size);
}

std::string readString(int sock)
{
    std::string value;
    int32_t size = readInt32(sock);
    if (size > 0) {
        value.resize(size);
        readRaw(sock, &value[0], size);
    }
    return value;
}
#包括
#包括
#包括“my_common_code.h”
void throwRuntimeError(const char*msg,int err)
{
std::ostringstream oss;

如果所示代码中有(msg&&*msg)oss,则如果编译器将
clientSocket
放在堆栈
player
下面,然后
std::cin>>player;
溢出并覆盖
clientSocket
。将
char player[1000];
更改为
std::string player;
,然后使用
send>(clientSocket,player.c_str(),player.length(),0)
@Remy我已经按照你说的做了更改,是的,我不再收到错误,但我现在收到了分段错误:(请发布一个。@MLin,那么您仍然在做我们看不到的其他错误。请提供一个显示您正在做什么的详细说明,并将
threadArgs参数的地址;
作为参数传递给
pthread\u create()
不安全。该结构位于主线程堆栈上,在子线程从中检索数据之前,它可能会超出范围。
#include <sstream>
#include <stdexcept>

#include "my_common_code.h"

void throwRuntimeError(const char *msg, int err)
{
    std::ostringstream oss;
    if (msg && *msg) oss << msg << ": ";
    oss << strerror(err);
    throw std::runtime_error(oss.str());
}

void throwRuntimeError(const char *msg)
{
    std::ostringstream oss;
    if (msg && *msg) oss << msg;
    throw std::runtime_error(oss.str());
}

void sendRaw(int sock, const void *data, size_t size)
{
    const char *pdata = static_cast<const char *>(data);
    while (size > 0) {
        ssize_t sent = send(sock, pdata, size, 0);
        if (sent < 0)
            throwRuntimeError("send", errno);
        pdata += sent;
        size -= sent;
    }
}

void readRaw(int sock, void *data, size_t size)
{
    char *pdata = static_cast<char *>(data);
    while (size > 0) {
        ssize_t recvd = recv(sock, pdata, size, 0);
        if (recvd < 0)
            throwRuntimeError("recv", errno);
        if (recvd == 0)
            throwRuntimeError("disconnected");
        pdata += sent;
        size -= sent;
    }
    return true;
}

void sendChar(int sock, char value)
{
    sendRaw(sock, &value, sizeof(value));
}

char readChar(int sock)
{
    char value;
    readRaw(sock, &value, sizeof(value));
    return value;
}

void sendBool(int sock, bool value)
{
    sendRaw(sock, &value, sizeof(value));
}

bool readBool(int sock)
{
    bool value;
    readRaw(sock, &value, sizeof(value));
    return value;
}

void sendInt32(int sock, int32_t value)
{
    value = htonl(value);
    sendRaw(sock, &value, sizeof(value));
}

int32_t readInt32(int sock)
{
    int32_t value;
    readRaw(sock, &value, sizeof(value));
    return ntohl(value);
}

void sendString(int sock, const std::string &value)
{
    int32_t size = value.length();
    sendInt32(sock, size);
    sendRaw(sock, s.c_str(), size);
}

std::string readString(int sock)
{
    std::string value;
    int32_t size = readInt32(sock);
    if (size > 0) {
        value.resize(size);
        readRaw(sock, &value[0], size);
    }
    return value;
}