Same socket for sending and receivng?
Ive read 'Beej's Networking Tutorials' just like the FAQ tells me too. And i tried to change the UDP talker-lister programm a bit, so the listener would sent an acknowledgement packet. But I can't use the socket with wich i send data to receive data aswell. What i do is this:
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
bind(sockfd,...);
sendto(sockfd, message,...);
recvfrom(sockfd,buf,...);
recvfrom then gives an error:
"recvfrom: No Error" (perror("recvfrom");)
So do i need another socket for receiving, or am i just being stupid?
I use Visual C++ and <winsock.h>
Thanks for reading this
In UDP, you can send and receive on the same socket.
However, if the socket is non-blocking, then calling recvfrom() will immediately return, even if there is no data.
Also, if you run two copies of the same program on the same machine, they can't both bind to the same port -- don't know if this is your problem or not -- it doesn't even really say what the actual error would be (your detection/printing code isn't part of the pasted code).
However, if the socket is non-blocking, then calling recvfrom() will immediately return, even if there is no data.
Also, if you run two copies of the same program on the same machine, they can't both bind to the same port -- don't know if this is your problem or not -- it doesn't even really say what the actual error would be (your detection/printing code isn't part of the pasted code).
well this is the source that i use. I copied it from the tutorial and changed it a bit for Visual C++. And the two programs worked. Then i just added Bind() and Recvfrom() to be able to send with the socket aswell.Its a regular blocking socket. If you compile it ull see what the problem is.
#define THEIRPORT 4950 // the port users will be connecting to#define MYPORT 4949#include <winsock.h>#include <iostream.h>#define MAXBUFLEN 100int main() { WSAData wsaData;// WSAStartup(MAKEWORD(2, 2), &wsaData); char buf[MAXBUFLEN]; int sockfd; struct sockaddr_in their_addr,my_addr; // connector's address information struct hostent *he; int numbytes; char message[100]; cin >> message; my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct if ((he=gethostbyname("Ramon")) == NULL) { // get the host info perror("gethostbyname"); cout << "Coulnt find host"; char chr[10]; cin >> chr; exit(1); } their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(THEIRPORT); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); cout << "Socket error"; char chr[10]; cin >> chr; exit(1); } if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); char chr[10]; cin >> chr; exit(1); } if ((numbytes=sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) { perror("sendto"); exit(1); } cout << numbytes <<" bytes where send to " << inet_ntoa(their_addr.sin_addr) <<endl; int addr_len = sizeof(struct sockaddr); if ((numbytes=recvfrom(sockfd,buf, MAXBUFLEN-1, 0, (struct sockaddr *)&their_addr,&addr_len)) == -1) { perror("recvfrom"); char chr[10]; cin >> chr; exit(1);//and this is where the programm stops } cout << numbytes << " received" << endl; cout << buf << endl; closesocket(sockfd); char chr[10]; cin >> chr; return 0; }
yay i fixed it. The problem was that the packet, that i send first, needs to be received, by the other programm, before i can recv a packet with the same socket. So i just added Sleep(100); and it works :)
Thanks anyway hplus0603!
Thanks anyway hplus0603!
Quote:Original post by xIshtarx
yay i fixed it. The problem was that the packet, that i send first, needs to be received, by the other programm, before i can recv a packet with the same socket. So i just added Sleep(100); and it works :)
Although this might smell like a nice fix right now, this isn't a good way to go about doing things. What if you are experiencing lag, and it takes more than 100ms for the packet to get back to you? Or what if another packet gets there ahead of the one you're expecting?
For your example, waiting is sufficient. Just keep these pitfalls in mind for when you write your next project. ;)
Thanks for the feedback.
It's my first networking programm, just to learn how UDP works. Btw if i want it non-blocking, i just use this?:
fcntl(sockfd, F_SETFL, O_NONBLOCK);
I dunno it it works for UDP aswell and that tutorial said:
Generally speaking, however, this type of polling is a bad idea. If you put your program in a busy-wait looking for data on the socket, you'll suck up CPU time like it was going out of style. A more elegant solution for checking to see if there's data waiting to be read comes in the following section on select().
I dont understand, why it would suck up CPU time. Can u use select on udp sockets aswell?
It's my first networking programm, just to learn how UDP works. Btw if i want it non-blocking, i just use this?:
fcntl(sockfd, F_SETFL, O_NONBLOCK);
I dunno it it works for UDP aswell and that tutorial said:
Generally speaking, however, this type of polling is a bad idea. If you put your program in a busy-wait looking for data on the socket, you'll suck up CPU time like it was going out of style. A more elegant solution for checking to see if there's data waiting to be read comes in the following section on select().
I dont understand, why it would suck up CPU time. Can u use select on udp sockets aswell?
It would suck up CPU time because if your socket is nonblocking, you'd just write a while() loop, looping while the return value is WSAEWOULDBLOCK, something like this:
select() allows your thread to sleep until a a message arrives.
Yes, you can use select() on UDP sockets.
do { int nRet = recv(...);} while((nRet == -1) && (WSAGetLastError() == WSAEWOULDBLOCK));
select() allows your thread to sleep until a a message arrives.
Yes, you can use select() on UDP sockets.
Do i really need to use threads? or can i just do something like this?
while(true){
Recv();
Send();
UpdateGame();
RenderGame();
}
Becus currently my game sucks up all the CPU time anyway :)
Could u point me some tutorials about multithreading (for networking)?
while(true){
Recv();
Send();
UpdateGame();
RenderGame();
}
Becus currently my game sucks up all the CPU time anyway :)
Could u point me some tutorials about multithreading (for networking)?
xIshtarx,
You don't need to use threads. In fact, the FAQ suggests that threads seldom help with networking games, and often hurt a bit.
The loop you suggest will work fine for a simple networked game, using non-blocking sockets. Once you get a little more fancy, you probably want to update physics on a fixed time-step basis, but keep the rest of the loop the same (including animation, which can run separate from physics).
You don't need to use threads. In fact, the FAQ suggests that threads seldom help with networking games, and often hurt a bit.
The loop you suggest will work fine for a simple networked game, using non-blocking sockets. Once you get a little more fancy, you probably want to update physics on a fixed time-step basis, but keep the rest of the loop the same (including animation, which can run separate from physics).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement