Sign in to follow this  

Data Packets

This topic is 3146 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am now working on sending Data with TCP/IP but I am still really new to Winsock2 so I need a little bit of information... It's hard to find any information on sending Data Packets with C++ in Winsock2 so here is my question I want to send two packets for commands(like: Accept, Refuse, VersionWrong, VersionRight, ChatMsg, AdminMsg, ServerMsg) basicly I want to send each command packet twice one packet is the buffer size then the other is the answer..but I am really unclear how this works.. I've been finding stuff like this:
char *sendbuf = "this is a test";
char recvbuf = [DEFAULT_BUFFER];
int recvbufflen = DEFAULT_BUFFER;
so what I need help with is how to send this data properly and accuratly. Or a link to a website that might help me, I've tried Bejee's but I get confused with his code, due to the fact it's not Wi32 it's Unix or what ever it is xD so thanks in advanced

Share this post


Link to post
Share on other sites
The Forum FAQ already answers this. You call send() on the integer value (preferably translated to network byte order), then you call send() on the actual data. If you worry about packet overhead and have turned off Nagling, then you want to send both at the same time, typically using WSASend() (or, under UNIX, writev()).

When receiving, you first receive the size of the length integer, translate it to host byte order, and then enter a loop that receives that many bytes (making sure that the indicated number of bytes isn't bigger than available buffer space).

Share this post


Link to post
Share on other sites
Ok, so instead of sending a string like "Account Accepted" can I number my packets like this..


#DEFINE PACKET_ACCEPT 1
#DEFINE PACKET_REJECT 2

/** etc etc **/



so when I send a accept or reject I send 1 or 2?

Share this post


Link to post
Share on other sites
You could, but if you ever wanted to change the numbering system, you would be in for a world of hurt.

I'd recommend simply using an enum so you can easily change numbering of sections of packet types with minimal efforts in case you need to cross that bridge in the future.

Share this post


Link to post
Share on other sites
Quote:
Original post by ARC inc
Care to explain?


Let's say you have 1000 packets defined as:

#define PACKET_TYPE_1 1
...
#define PACKET_TYPE_1000 1000


Let's say cheaters map out all those opcodes and release a cheat that is hardcoded to those values. To break those cheats, you want to change all of the opcode values. Lots of fun, right?

If instead you used an enum, you'd have
enum Packet_Type
{
Type1 = 0,
...
Type1000
};

and a way easier job of changing the opcode values without much work as you can arbitrarily change certain ranges of opcodes by using the rules of enums. For example:
enum Packet_Type
{
Type1 = 10,
...
Type20 = 150
...
Type30 = 20
...
Type1000
};


Hope that helps.

Share this post


Link to post
Share on other sites
I just number them. I've never liked the C++ enum. I use a class for each of the ServerEvents and ClientEvents so I can just access them like ServerEvents::PING and such. Simple.

#pragma once

class ServerEvents
{
public:
const static unsigned short ENTITY_UPDATES = 1;
const static unsigned short REMOVE_PLAYER = 2;
const static unsigned short UPDATE_BOUNDARIES = 3;
const static unsigned short PING = 4;
};




I also use a binary buffer for writing messages. I should rewrite this article, but it will do:
Old article on packet formatting
I've used it for a few projects and it works really well.

Also make your server authoritative.

Share this post


Link to post
Share on other sites
Ok, so new question!

I am wanting to make threads in my Server Architect so I can accept more then just a single connection..

After reading MSDN on Winsock2 it says something about SOMAXCON...Does that mean I need to change that into how many connections it waits for? or do I do something else...please help!!!

here is my listen code..

if(listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen Failed: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}


thanks in advanced once again :D

Share this post


Link to post
Share on other sites
No, the SOMAXCON is just for the backlog of pending connections. For a one thread per socket approach you just need to pass each socket you create via accept() into the thread you've made for it, and you're done.

Note however that you do not need to have multiple threads to handle more than one socket. The typical way is to use select() on a collection of sockets (often including your listening socket) to tell you which ones are ready to give you data at a given point.

Share this post


Link to post
Share on other sites
Quote:
Original post by ARC inc
Well the way I read is that you need to have a thread to accept more then one connection at a time...


Luckily you don't. If that was the case, programming even the simplest server would be a nightmare. =)

Share this post


Link to post
Share on other sites
Quote:
I am wanting to make threads in my Server Architect so I can accept more then just a single connection.


Please read the Forum FAQ. There is no direct correlation between threads and clients in general. For someone starting out with network programming, using select() is fine, and can do 64 connections on Windows, and about a thousand on UNIX. Once you have that working fine, and actually have more than 60 simultaneous users, you can start looking into more advanced systems.

Also, if you're using UDP, you only need a single socket no matter how many "connections" you have.

Share this post


Link to post
Share on other sites
Ok, so I have my basic server done but I am getting errors with it....can someone help me please?

#include <winsock2.h>
#include "config.hpp"
#include "util.hpp"
#include <stdio.h>

class server
{
private:

WSADATA wsaData;

int ErgoServ = WSAStartup(MAKEWORD(2,2), &wsaData);

if(ErgoServ != 0){
printf("WSAStartup Failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

SOCKET s = socket(AF_INET, SOCK_STREAM, 0);

if(s == INVALID_SOCKET){
printf("Socket creation failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

sockaddr_in sin;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_family = AF_INET;

if(bind(s(sockaddr*)&sin sizeof(sin)) == SOCKET_ERROR){
printf("Bind failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

while(listen(s, SOMAXCONN) == SOCKET_ERROR);

SOCKET client;

int lin = sizeof(sin);
client = accept(s,(sockaddr*)&sin, &lin);
printf("Connection Establised");

char buf[80] = PACKET_WELCOME;
send(client,buf,sizeof(buf),0);
closesocket(s);
closesocket(client);
WSACleanup();
return 0;
}




||=== Test, Debug ===|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: `int WSAStartup(WORD, WSADATA*)' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: `server::wsaData' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: `&' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: a function call cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: ISO C++ forbids initialization of member `ErgoServ'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: making `ErgoServ' static|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|error: ISO C++ forbids in-class initialization of non-const static member `ErgoServ'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|14|error: expected unqualified-id before "if"|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|error: `SOCKET socket(int, int, int)' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|error: a function call cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|error: ISO C++ forbids initialization of member `s'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|error: making `s' static|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|error: ISO C++ forbids in-class initialization of non-const static member `s'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|22|error: expected unqualified-id before "if"|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|29|error: ISO C++ forbids declaration of `sin' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|29|error: expected `;' before '.' token|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|30|error: ISO C++ forbids declaration of `sin' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|30|error: expected `;' before '.' token|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|31|error: ISO C++ forbids declaration of `sin' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|31|error: expected `;' before '.' token|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|33|error: expected unqualified-id before "if"|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|39|error: expected unqualified-id before "while"|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|28|error: invalid use of non-static data member `server::sin'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|43|error: from this location|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|43|error: ISO C++ forbids initialization of member `lin'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|43|error: making `lin' static|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|43|error: ISO C++ forbids in-class initialization of non-const static member `lin'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `SOCKET accept(SOCKET, sockaddr*, int*)' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `server::s' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `server::sin' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `&' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: a casts to a type other than an integral or enumeration type cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `server::lin' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `&' cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: a function call cannot appear in a constant-expression|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: ISO C++ forbids declaration of `client' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: ISO C++ forbids initialization of member `client'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: making `client' static|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: ISO C++ forbids in-class initialization of non-const static member `client'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: declaration of `int server::client'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|41|error: conflicts with previous declaration `SOCKET server::client'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|45|error: expected identifier before string constant|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|45|error: expected `,' or `...' before string constant|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|45|error: ISO C++ forbids declaration of `printf' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|45|error: ISO C++ forbids declaration of `parameter' with no type|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|47|error: `PACKET_WELCOME' was not declared in this scope|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|47|error: ISO C++ forbids initialization of member `buf'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|47|error: making `buf' static|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|47|error: invalid in-class initialization of static data member of non-integral type `char[80]'|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|48|error: `client' is not a type|
||More errors follow but not being shown.|
||Edit the max errors limit in compiler options...|
||=== Build finished: 50 errors, 0 warnings ===|

Thouse are the errors..I haven't read through them all most of them I can fix myself but some of the networking errors I am having problems with...

Thanks to all that have been helping me through this post :D

Share this post


Link to post
Share on other sites
Inside a class, you may only put declarations *. You need to move the code to a function body.

Think about the data the server needs to keep between functions. This is its state. Your server will probably want to store the listen socket, as well as the sockets of each of its clients. These are its private member variables. The other values would be local variables inside various functions.

* In general. You can define small functions and initialise static const integral values.

Share this post


Link to post
Share on other sites
ok, so I rewrote my server function stuff, so it uses

int serverstart(){

but now I am getting errors with '*' it says like expected error with primary function '*'

Share this post


Link to post
Share on other sites
||=== Test, Debug ===|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h||In function `int serverstart()':|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|12|warning: char format, different type arg (arg 2)|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|20|warning: char format, different type arg (arg 2)|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|30|error: expected primary-expression before '*' token|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|30|error: expected primary-expression before ')' token|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|30|error: `s' cannot be used as a function|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|31|warning: char format, different type arg (arg 2)|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|error: `PACKET_WELCOME' was not declared in this scope|
C:\Documents and Settings\Dev\Desktop\Ergo\Test\socket.h|44|warning: unused variable 'PACKET_WELCOME'|
||=== Build finished: 4 errors, 4 warnings ===|

an it's all the same code cept I am not using the class server

I am using

int serverstart(){

//All my Server Code: WSADATA etc etc...

}



-Edit- I know the PACKET_WELCOME problem ignore that error

Share this post


Link to post
Share on other sites
The error message "char format, different type arg (arg 2" is because you are using printf incorrectly. Your printf messages should be like this:

printf("<operation> failed: %s\n", WSAGetLastError());


Some of your other errors might be related to lines like this:

bind(s(sockaddr*)&sin sizeof(sin))

You probably want a commas between your arguments "s", "(sockaddr*)&sin" and "sizeof(sin)".

For future reference, please copy and paste the exact code. It actually requires less effort than typing up a skeleton, and shows us very clearly what is going on. I had to scroll up and down trying to match the error messages in your later post with the code from your earlier one.

A final comment. The kind of error messages you are getting have nothing to do with sockets or network programming. They are basic C++ language problems. If you cannot solve them, that indicates to me that you are going too fast.

Trying to do network programming when you are still a beginner at C++ will probably only cause you a lot of pain and frustration. I would advise that you stick to simpler programs, and move on when you feel you are ready.

Share this post


Link to post
Share on other sites
Ok, so I added the comma's like you said..but I am still getting some issues...same errors.

#include <winsock2.h>
#include "config.hpp"
#include "util.hpp"
#include <stdio.h>
int serverstart(){

WSADATA wsaData;

int ErgoServ = WSAStartup(MAKEWORD(2,2), &wsaData);

if(ErgoServ != 0){
printf("WSAStartup Failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

SOCKET s = socket(AF_INET, SOCK_STREAM, 0);

if(s == INVALID_SOCKET){
printf("Socket creation failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

sockaddr_in sin;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_family = AF_INET;

if(bind(s,(sockaddr*),&sin sizeof,(sin)) == SOCKET_ERROR){
printf("Bind failed: %s\n", WSAGetLastError);
WSACleanup();
return 1;
}

while(listen(s, SOMAXCONN) == SOCKET_ERROR);

SOCKET client;

int lin = sizeof(sin);
client = accept(s,(sockaddr*)&sin, &lin);
printf("Connection Establised");

char buf[80] = PACKET_WELCOME;
send(client,buf,sizeof(buf),0);
closesocket(s);
closesocket(client);
WSACleanup();
return 0;
}



Also so you know I am not as new to C++ as it may seem; I've been working with it for awhile(a year maybe less) I learn better by doing the harder things then the easier things..I know it's weird an you probably don't believe me but thats ok, everyone learns differently..

Thanks again for everyone's help

Share this post


Link to post
Share on other sites
I've already pointed out that your printf messages are incorrect and how you should fix them. Maybe you should drop printf (which you may have kept because a tutorial included it) and use the C++ streams instead, which you may be more familiar with:

if(/* something went wrong */){
std::cerr << "Something Failed: " << WSAGetLastError() << '\n';
WSACleanup();
return 1;
}


Also you have gotten the commas almost completely wrong. I separated the arguments for you into quoted strings, but you have ignored that and inserted commas seemingly at random.

I appreciate that you like to learn by trying hard things. But if your current difficulty is with the C++ language then why not challenge yourself by concentrating on learning that?

Share this post


Link to post
Share on other sites
You don't even know C++ programming. There is no way that you should be working on networking code in C++ right now; you need to first learn the language before you'll have any chance of writing useful networking code.

Share this post


Link to post
Share on other sites

This topic is 3146 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this