我正在實施C++客戶端服務器聊天程序以瞭解更多/練習套接字編程。我正在使用winsockV2。recv()字符數組大小
簡而言之, 客戶端程序連接到服務器,該服務器將客戶端套接字存儲在向量中 客戶端程序發送消息供服務器分發給向量中的其他客戶端。
我想我遇到的問題是,客戶端和服務器正在接收消息並將其存儲在char message[256]
中,如果消息比256短,當我正在存儲的std::cout << message;
中顯示奇怪的字符被告知是未初始化的內存。下面是一個輸出示例:
k:message from client to other client╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠(■o
是否有某種方法可以創建接收消息大小的字符數組?即
char recvMessage[4096];
int s = recv(socket, recvMessage, sizeof(recvMessage),0);
char recvOutput[strlen(recvMessage)] = recvMessage;
std::cout << recvOutput << std::endl;
否則,什麼是你的recv
解決方案「荷蘭國際集團,你不知道的長度的消息?
如果我是一個完全白癡,請友好,我來自PHP。類是如下:
SVR.CPP參見receiveMessages()
distributeMessages()
和功能
#include "stdafx.h"
#include "svr.h"
svr::svr()
{
//WSA Business I don't understand
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
}
//End of WSA Business
//get addressSize
addressSize = sizeof(address);
//set address data members
address.sin_family = AF_INET;
address.sin_port = htons(444);
address.sin_addr.s_addr = INADDR_ANY;
//init sListen
sListen = socket(AF_INET, SOCK_STREAM, 0);
bind(sListen, (sockaddr*)&address, addressSize);
}
svr::~svr()
{
}
void svr::start()
{
std::thread newConnThread(&svr::newConnection, this);
newConnThread.join();
}
void svr::receiveMessages(int clientIndex)
{
std::cout << "\tsvr::recv thread started for client index:" << clientIndex << std::endl;
//create char arr
char recvMessage[256];
//forever
while (true)
{
//receive message and input it to recvMessage char arr.
recv(clients[clientIndex], recvMessage, sizeof(recvMessage), 0);
//if message is not null, send out to other clients
if (recvMessage != NULL)
{
std::cout << "\t\tINFO:Received message of length: " << std::strlen(recvMessage) << " size: " << sizeof(recvMessage) << " : " << recvMessage << std::endl;
distributeMessages(recvMessage, clientIndex);
}
}
}
//distributes messages to all clients in vector. called by receiveMessages function, normally in rMessages thread.
void svr::distributeMessages(std::string message, int clientIndex)
{
for (unsigned int i = 0; i < clients.size(); i++)
{
if (clientIndex != i)
{
send(clients[i], message.c_str(), message.length(), 0);
}
else
{
//would have sent to self, not useful.
}
}
}
//accepts new connections and adds sockets to vector.
void svr::newConnection()
{
//mark for accept, unsure of somaxconn value;
listen(sListen, SOMAXCONN);
std::cout << "\tSERVER: awaiting new connections..." << std::endl;
while (true)
{
//accept connection and push on to vector.
clients.push_back(accept(sListen, (sockaddr*)&address, &addressSize));
//responds to new clients.
const char *message = "Hi, you've successfully connected!";
int clientIndex = clients.size() - 1;
int sent = send(clients[clientIndex], message, 33, 0);
//start new receiveMessage thread
std::thread newClient(&svr::receiveMessages, this, clientIndex);
//detach here, let newConn thread operate without depending on receiveMessages
newClient.detach();
}
std::cout << "\tSERVER: no longer listening for new connections" << std::endl;
}
CLI.CPP
參見cSend()
和cRecv()
功能
#include "stdafx.h"
#include "cli.h"
cli::cli(char *ip)
{
//WSA
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
// Use the MAKEWORD(lowbyte,highbyte) macro declared in windef.h
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
std::cout << "WSAStartup failed with the error: " << err;
}
}
//get addressSize
addressSize = sizeof(address);
//set address struct data members
address.sin_family = AF_INET;
address.sin_port = htons(444);
//if ip empty, prompt user;
if (ip == NULL)
{
std::string ipInput;
std::cout << "\n\tConnect to which IP: ";
std::cin >> ipInput;
address.sin_addr.s_addr = inet_addr(ipInput.c_str());
}
else
{
address.sin_addr.s_addr = inet_addr(ip);
}
sock = socket(AF_INET, SOCK_STREAM, 0);
std::cout << "\n\tYour username: ";
std::cin >> uname;
}
cli::~cli()
{
}
void cli::start()
{
try
{
//hold string
char message[33];
std::cout << "\n\tcli::start() called";
int conRet;
//connects to server socket & receives a message, stores in it message variable
conRet = connect(sock, (sockaddr*)&address, (int)addressSize);
recv(sock, message, sizeof(message), 0);
std::cout << "\n\tSERVER: " << message;
//starts threads, pass this for object scope.
std::thread sendThread(&cli::cSend, this);
std::thread recvThread(&cli::cRecv, this);
//this function (start) will return/end when send and recv threads end.
sendThread.join();
recvThread.join();
}
catch (std::exception e)
{
std::cerr << e.what() << std::endl;
}
}
void cli::cSend()
{
std::cout << "\n\tcli::send thread started";
//char arr for sending str;
std::string getLine;
while (true)
{
std::cout << "\n\t" << uname << ":" << std::flush;
//set to "" because i suspected the value remains in the string after a loop.
std::string message = "";
//get input, put it in message
std::getline(std::cin, message);
//get full message
std::string fullMessage = uname + ":" + message;
//get constant int, size of fullMessage
const int charArrSize = fullMessage.length();
std::cout << "\t\tINFO: Sending character array of length: " << charArrSize << " size: " << sizeof(fullMessage.c_str()) << " : " << fullMessage.c_str() << std::endl;
//sends it
send(sock, fullMessage.c_str(), charArrSize, 0);
}
}
void cli::cRecv()
{
std::cout << "\n\tcli::recv thread started";
//initialize arr to 0, will hopefully help avoid the weird chars in the cout
char recvMessage[256]{ '\0' };
while (true)
{
recv(sock, recvMessage, sizeof(recvMessage), 0);
std::cout << "\t\tINFO:Received message of length: " << std::strlen(recvMessage) << " size: " << sizeof(recvMessage) << " : " << recvMessage << std::endl;
std::cout << recvMessage << std::endl;
}
}
感謝您的詳細信息。我沒想過要使用返回值! 使用std :: string構造函數,我知道第二個參數是大小,但爲什麼使用'recvMessage + s'? – spkvn