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