Ir ao conteúdo

Ajuda com C++


Takutanuva

Posts recomendados

Postado

Eu comecei a ler um tutorial de C++ fazem uns 5 dias, ainda sou novato nisso... Estou desenvolvendo um jogo, tentei faze-lo em ruby, mas ele estava muito lento, por isso decidi tentar faze-lo em C++... Eu comecei o servidor do jogo, e quando eu testo aqui, com um cliente improvisado, no mesmo computador, ele funciona sem problemas... Quando eu peço para um amigo rodar o servidor, e eu rodo o cliente, aparece uma mensagem de erro no servidor, dizendo que o programa executou uma operação ilegal e será fechado... Tentei fazer um cliente em ruby como tira-teima, e o problema persistiu... Alguem pode me dizer qual o problema? Obrigado.

Socket.cpp:

#include "socket.h"
CSERVER::CSERVER(int port) {
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == SOCKET_ERROR) {
printf("Error Opening Socket!\n");
};
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
int error;
error = bind(sock, (sockaddr*)&server, sizeof(server));
if (error == SOCKET_ERROR) {
printf("Bind Failed!\n");
sock = SOCKET_ERROR;
};
error = listen(sock, 5);
if (error == SOCKET_ERROR) {
printf("Listen Failed!\n");
sock = SOCKET_ERROR;
};
};
CCLIENT CSERVER::Accept() {
int clientSocket;
clientSocket = accept(sock, 0, 0);
return CCLIENT(clientSocket);
};
CSERVER::~CSERVER() {
closesocket(sock);
};
int StartW2Sock() {
int error;
WSAData wsaData;
error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (error == SOCKET_ERROR) {
printf("Could Not Start Up Winsock!\n");
return 1;
}
return 0;
};
string CCLIENT::Recv() {
int nBytes;
char buffer[BUFFER_SIZE];
unsigned long messageSize;
nBytes = recv(sock, (char*)&messageSize, sizeof(messageSize), 0);
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
messageSize = ntohl(messageSize);
nBytes = recv(sock, buffer, messageSize, 0);
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
buffer[messageSize] = '\0';
//~ printf("Message Received : %s\n", buffer);
return buffer;
};
void CCLIENT::Send(string msg) {
int nBytes;
char buffer[BUFFER_SIZE];
sprintf(buffer, msg.c_str());
unsigned long messageSize = strlen(buffer);
messageSize = htonl(messageSize);
nBytes = send(sock, (char*)&messageSize, sizeof(messageSize), 0);
if (nBytes == SOCKET_ERROR) {
printf("Send Failed!\n");
};
messageSize = ntohl(messageSize);
nBytes = send(sock, buffer, messageSize, 0);
if (nBytes == SOCKET_ERROR) {
printf("Send Failed!\n");
};
};
CCLIENT::~CCLIENT() {};

Socket.h:

#ifndef _H_SOCKET_
#define _H_SOCKET_
#define BUFFER_SIZE 4096
#include <winsock2.h>
#include <stdio.h>
#include <string>
#include <iostream>
#pragma comment(lib, "libws2_32.a")
using namespace std;
class CCLIENT {
public:
CCLIENT(int sock_):sock(sock_) {};
string Recv();
void Send(string msg);
int Sock() { return sock; };
~CCLIENT();
private:
int sock;
};
class CSERVER {
public:
CSERVER(int port);
CCLIENT Accept();
int Sock() { return sock; };
~CSERVER();
private:
int sock;
};
int StartW2Sock();
#endif

Main.cpp:

#include <cstdlib>
#include <iostream>
#include <string>
#include "players.h"
#include "options.h"
#include "socket.h"
#include "windows.h"
//#include <winsock2.h>
//#include <stdio.h>
//#pragma comment(lib, "libws2_32.a")
using namespace std;
string *lol;
void threadProc() {
int count = 0;
int timer = time(NULL);
while(true) {
count++;
if(timer!=time(NULL)) {
timer = time(NULL);
cout << count << endl;
count = 0;
};
};
};
int main(int argc, char *argv[])
{
cout << StartW2Sock() << endl;
cout << Options.Port() << endl;
CSERVER server(Options.Port());
cout << "Servidor iniciado com sucesso!" << endl;
CCLIENT client = server.Accept();
cout << "Cliente aceito!!! Yuhul XD" << endl;
//HANDLE threadHandle;
//threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, NULL, 0, NULL);
int timer = time(NULL);
int count = 0;
while(true) {
string msg = client.Recv();
count += msg.size();
if(timer!=time(NULL)) {
timer = time(NULL);
cout << count << " bps" << endl;
count = 0;
};
};
delete[] lol;
system("PAUSE");
WSACleanup();
return EXIT_SUCCESS;
};

Edit:

Bem, eu fiz varios testes... Quando eu botei uma pausa entre uma mensagem e outra, ele parou de dar erro... Mas quando eu aumentei a mensagem, sem mudar o tempo da pausa (Sleep), ele deu erro... Aumentei a pausa, e funcionou novamente... Mas não sei se isso pode ajuda...

Alguem pode me ajudar?

Postado

O Sleep e as mensagens estão no cliente, botei uma pausa entre as mensagens que ele envia para o server. Eu não sei bem qual o problema, não tenho nem ideia... Alguém tem ideia do que pode ter causado o problema?

  • Membro VIP
Postado

Não conferi todo o código ta um pouco corrido aqui, o trecho abaixo me parece com um detalhe errado:


string CCLIENT::Recv() {
int nBytes;
char buffer[BUFFER_SIZE]; // Uma variavel local, sera destruída ao sair da função
unsigned long messageSize;
nBytes = recv(sock, (char*)&messageSize, sizeof(messageSize), 0);//gpf caso messageSize seja maior que BUFFER_SIZE;
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
messageSize = ntohl(messageSize);
nBytes = recv(sock, buffer, messageSize, 0);
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
buffer[messageSize] = '\0';
//~ printf("Message Received : %s\n", buffer);
return buffer;//buffer é uma variavel local, sera destruída ao sair da função e quem chamou tera informações que podem ser inválidas.
};

Uma forma simple de corrigir:


string CCLIENT::Recv() {
int nBytes;
char* buffer; // apenas um ponteiro, o buffer mesmo não sera destruído
unsigned long messageSize;
nBytes = recv(sock, (char*)&messageSize, sizeof(messageSize), 0);
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
messageSize = ntohl(messageSize);
buffer = new char[messageSize + 1];//aloca o necessário para a mensagem e um '\0' no final.
nBytes = recv(sock, buffer, messageSize, 0);
if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};
buffer[messageSize] = '\0';
return buffer;//lembrar de liberar a memória alocada quando não estiver mais em uso.
};

Só isso talvez não resolva o erro, e qual o erro que esta dando e como esta o código no cliente?

Postado

Bem, agora não dá mais o erro.:lol::lol::lol:

Mas... A taxa tava a 0.3kbps (arrumei o contador), alguém sabe como melhora isso?:(

Pro cliente, copiei o server e modifiquei algumas coisas:

Socket.cpp:

int startupClient(unsigned short port, const char* serverName) {
int error;
int mySocket = socket(AF_INET, SOCK_STREAM, 0);
if (mySocket == SOCKET_ERROR) {
printf("Error Opening Socket!\n");
return -1;
}
struct hostent *host_entry;
if ((host_entry = gethostbyname(serverName)) == NULL) {
printf("Could not find host!\n");
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;
if (connect(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Error connecting to server!\n");
}
printf("Client Started\n");
return mySocket;
}

Main.cpp:

int main(int argc, char *argv[])
{
cout << StartW2Sock() << endl;
cout << Options.Port() << endl;
CCLIENT client("valoriam.servegame.com", Options.Port());
cout << "lol" << endl;
//HANDLE threadHandle;
//threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, NULL, 0, NULL);
while(true) {
string msg = client.Recv();
client.Send(msg);
};
delete[] lol;
system("PAUSE");
WSACleanup();
return EXIT_SUCCESS;
};

Obrigado.

Postado

Tipo de conexão? Não entendi bem, mas acho que é TCP...

De onde para onde... Eu testei com um amigo em São Paulo (eu sou de Joinville, SC), e testei com um amigo aqui da mesma cidade, não moro muito longe dele. O resultado foi o mesmo. Só se eu testar no mesmo computador que ele chega a 70kbps. Mas com computadores diferentes, não passa de 0.4kbps... Não sei por que, até mesmo em ruby eu conseguia 20kbps.

A mensagem não representa nada, botei uma mensagem qualquer pra testa a velocidade, mandei "<lol>teste</lol>".

  • Membro VIP
Postado

Desculpe, não me espressei bem, quis dizer a velocidade da conexão.

Mas pela mensagem ja vi que nãos era necessário.

Pelo código você recebe a mensagem e reenvia, espera até receber de novo e continua assim para medir a velocidade, certo?

Pode tentar "pingar" o computador do seus amigos, o resultado deve ser mais ou menos 50 ms, o que permite no máximo 20 msgs por segundo, com 16 byte por msg da 0.3KB/s.

Você pode aumentar isso enviando e recebendo de forma assincrona, enviando mais bytes por msg e alterando a forma de determinar o tamanho da mensagem, a cada "send" ele vai enviar um pacote e esse pacote tem um tamanho mínimo, o primeiro "send" envia apenas 8 bytes (com o tamanho da mensagem) e o segundo no seu teste apenas 16 tente manter o tamanho do pacote entre 1KB e 8KB, coloque o tamanho da mensagem nos primeiros bytes dela (você pode usar dois "recv" para ler apenas um "send" sem grandes perdas) ou determinar um tamanho fixo para todas as mensagens.

Postado
você pode usar dois "recv" para ler apenas um "send" sem grandes perdas

Bem... Desculpe, mas... Como eu junto os dois sends?:unsure:

Ainda estou aprendendo, não sei muito bem mexer com strings...

  • Membro VIP
Postado

void CCLIENT::Send(string msg) {
int nBytes;
char buffer[BUFFER_SIZE];
unsigned long messageSize;
sprintf(buffer + sizeof(messageSize), msg.c_str());
messageSize = strlen(buffer + sizeof(messageSize));
*((unsigned long*)buffer) = htonl(messageSize);
nBytes = send(sock, buffer, messageSize + sizeof(messageSize), 0);
if (nBytes == SOCKET_ERROR) {
printf("Send Failed!\n");
};
};

Postado

Bem, este codigo substituiu os 4 primeiros caracteres da mensagem em si, e depois de um tempo rodando ele fexa sem avisa nenhum erro, simplesmente fexa.

Postado

Ele fexa já na primeira mensagem. Eu fiz um cliente improvisado em ruby para mostrar a mensagem, com o metodo antigo (2 sends) ele enviava no começo "\000\000\000\020" (20, o tamanho da mensagem), agora ele está enviando "\000\000\000\000" no começo, talvez isso tenha causado o erro.

Postado

Quando eu tirei aquela espera (esperar receber a mensagem para re-enviala), botei apenas para ficar enviando, o fechou novamente. Mas, tudo bem, eu vou procurar mais tutoriais sobre sockets para descobrir o motivo. Agradeço muito pela ajuda.

  • Membro VIP
Postado

Pra te ajudar um pouco com o debug...


if (nBytes == SOCKET_ERROR) {
printf("Recv Failed!\n");
};

Esse trecho aparece algumas vezes no seu código, alem de retornar SOCKET_ERROR ele pode retornar 0 quando fecha a conexão e seria bom tartar ai tambem, e só com esse printf depois ele vai continuar o programa com valores inválidos, o que fara dar erro em algum outro lugar e fechar, coloque um pause e um exit depois desses printf.

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!