I am trying to make a program using Winsock2 where I can send a message from client to server. I can do this, but the problem is I can only send one message and then I have to restart the server to receive the next message. Here is the code for the server. The part I am really confused about is I have the recv() function in a while loop so why isn't it continuing to "receive" data?
WSADATA wsaData;
int bytes_recieved;
char data_recieve[2048];
string output;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN ServerInfo;
ServerInfo.sin_family = AF_INET;
ServerInfo.sin_addr.s_addr = INADDR_ANY;
ServerInfo.sin_port = htons(8888);
bind(ListenSocket, (LPSOCKADDR)&ServerInfo, sizeof(struct sockaddr));
listen(ListenSocket, 1);
SOCKET ClientSocket = accept (ListenSocket, NULL, NULL);
while(true)
{
bytes_recieved = recv(ClientSocket, data_recieve, 2048, 0);
if (bytes_recieved > 1)
{
cout << data_recieve;
}
}
closesocket(ClientSocket);
closesocket(ListenSocket);
WSACleanup();
The client (sender) is listed below.
WSADATA wsaData;
int bytes_sent;
char send_msg[] = "super cool message!";
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in ConnectInfo;
ConnectInfo.sin_family = AF_INET;
ConnectInfo.sin_addr.s_addr = inet_addr("127.0.0.1");
ConnectInfo.sin_port = htons(8888);
connect(ConnectSocket, (SOCKADDR*)&ConnectInfo, sizeof(ConnectInfo));
bytes_sent = send(ConnectSocket, send_msg, sizeof(send_msg), 0);
closesocket(ConnectSocket);
WSACleanup();
I am doing this in Windows 7 with a MinGW compiler. Thank you in advance.
You did not show your client sending code, but offhand, your server reading code is not taking into account that sends and receives are NOT 1-to-1 in TCP/IP programming. If a client sends 2 messages, the server may receive both messages, or even portions of them, in the same read operation! You ae telling your server socket to read 2048 bytes at a time. It will return whatever is currently available on the socket at that moment. TCP/IP is a byte stream, you need to treat it as much. That means you need to either put a delimiter in between your messages, or put a frame around them, in order to know where one message ends and the next message begins.
Related
I am using the WinSock API in C++ to connect and send data to a specific server (to increase readability, all the code is without error handling):
#include <winsock2.h>
#include <Windows.h>
#define PORT 5051
WSADATA WsaData;
WSAStartup(MAKEWORD(2, 2), &WsaData);
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sin;
ZeroMemory(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr("Some valid IP");
connect(s, (sockaddr *) &sin, sizeof(sin));
string sdata_out = "Something like GET request\n";
send(s, sdata_out.c_str(), sdata_out.size(), 0);
The server will start to sending responses, separated by different periods of time. It will send responses without additional requests from me.
I need to read this data asynchronously (not cycle of recv() functions).
I tried to use WSAEventSelect() to listen on the local socket, like this:
SOCKET sloc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sinloc;
ZeroMemory(&sinloc, sizeof(sinloc));
sinloc.sin_family = AF_INET;
sinloc.sin_port = htons(PORT);
sinloc.sin_addr.s_addr = INADDR_ANY;
WSAEventSelect(sloc, EventArray[EventTotal - 1], FD_ACCEPT |
FD_CLOSE | FD_READ | FD_CONNECT) == SOCKET_ERROR)
bind(sloc, (sockaddr *)&sinloc, sizeof(sinloc));
listen(sloc, 5));
I have no idea what to do further. I tried following this example, but my program got stuck at runtime on this code:
DWORD Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)
What is the problem? How should my event handler function look? Or, am I am doing something fundamentally wrong? Is there a correct way to asynchronously read data from the server, if I don't know when the data comes?
i have problem because my server dont get UDP data. Ports on router are forwarded, data income to local-server network (it is visible on sniffer (3) ) but server dont receive it.
Server and server network screen
You can see 1 and 2 TCP packets correct income to server on connected sockets. But my client then send UDP data to server and data enter to local-server network (see that sniffer detect it on 3) but server dont take it.
Here is code of client:
struct sockaddr_in si_other;
int s, slen = sizeof(si_other);
char buf[10];
char message[10];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(14996);
si_other.sin_addr.S_un.S_addr = inet_addr(server ip);
memcpy(message, "cokolwiek", 8);
//send the message
if (sendto(s, message, strlen(message), 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
But its not problem with client. Here is server code but i think it is also correct:
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[10];
WSADATA wsa;
slen = sizeof(si_other);
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(14996);
//Bind
if (::bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//blocking on it, waiting for data
if ((recv_len = recvfrom(s, buf, 10, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n", buf);
Some description that may help - main server loop is select() and when client ask for order, server send order back to client and starts proceeding command.
server:
while (1) {
select()
if (socket is in FD_SET)
get data, send it back and handleCommand()
}
handleCommand() {
tcp data exchange
wait for udp packet - it fail
}
client:
sendCommand()
//another receiving commands thread
while (recv) {
handle command
tcp data exchange
send udp data
}
Pls dont give me answears to do it in another wait. I need to punch hole for NAT Traversal. What problem is that? Another listener grabbing my data? But netstat -nop UDP -a didn't give information that something other is listening, and bind socket didn't failed. Also another important information That code work on the begining of program, i mean server receive data but later not.
Okey, so as ElderBug said
Are you sure you setup the UDP server socket before you send the data ? It's not clear in your question
Yep, it was my fault. The miniseconds decided that sending data on one machine was executed before setting up listener on server. Thank you for answer.
But i dont exactly understand the problem. Shouldn't that data income to receive buffer and wait for "grabbing" it by recvfrom function?
I'm trying to write a simple client and server using UDP.
I can send data from the client to the server, and the server recieves it well, but when I send the data from the server to the client, it doesnt work at all...
(It doesnt detect anything, and is stuck on recvfrom function..
Here is my Server code :
SOCKET ServerOn()
{
SOCKET ListenSocket;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
exit(0);
}
// Create a SOCKET for listening for
// incoming connection requests.
ListenSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_port = htons(2583);
if (bind(ListenSocket,(SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR)
{
closesocket(ListenSocket);
WSACleanup();
exit(2);
}
return ListenSocket;
}
In this function, I'm initializing the server on port 2583.
Here is my other code in the server :
int size = sizeof(service);
char *data = new char[500];
recvfrom(s,data, 500, NULL, (SOCKADDR*)&service, &size); // Getting a new connection
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
int addrSize = sizeof(service);
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize) != 3)
printf("%d", WSAGetLastError()); // Print error if did not send successfully
"10.0.0.1" is the IP of the Client (I made sure it is)...
I didnt found a way to get the IP automaticly from the socket, so I'm just putting it right away for now...
Here is my client code :
SOCKET ConnectToServer()
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
return NULL;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ConnectSocket == INVALID_SOCKET)
{
WSACleanup();
return NULL;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(Default_IP.c_str()); // IP
clientService.sin_port = htons(Default_Port); // Port
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
while (iResult == SOCKET_ERROR) // ERROR, could not connect. keep trying
{
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
}
return ConnectSocket;
}
In this code, I'm connecting to the client.
and here is the rest of the client code :
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
s = ConnectToServer();
sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize);
while(true)
{
result = recvfrom(s, (char*)waveIn, NUMPTS * sizeof(short int), NULL, (struct sockaddr *)&service, &addrSize);
if (result > 0)
{
std::cout << "New Data!" << std::endl;
}
else
printf("%d\n", WSAGetLastError());
}
the sendto function in the client does work, and the server recieves it, though when the server tries to send data back to the client, it recieves nothing, and it is stuck on the recvfrom function.
What am I doing wrong?
P.S - I'm running both client and server from the same computer, which means both has the same IP adress ("10.0.0.1"), but it allways worked for me when using sockets with TCP, so I've did it here too.
though, I did try use this code with 2 different computers, and I still had the same error...
Thanks!
When the server calls recvfrom(), it reports the IP:Port that the data came from. You need to send your reply back to that same IP:Port, eg:
sockaddr_in service;
int size = sizeof(service);
char data[500];
int len = recvfrom(s, data, 500, NULL, (SOCKADDR*)&service, &size);
if (len == -1)
printf("recv failed: %d", WSAGetLastError()); // Print error if did not recv successfully
else
{
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, size) == -1)
printf("send failed: %d", WSAGetLastError()); // Print error if did not send successfully
}
I have something like this in my code
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (5005);
target.sin_addr.s_addr = inet_addr ("127.0.0.1");
clntSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (::connect(clntSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
//Could not connect
__debugbreak();
}
else
{
//Connected - Now receive data
do
{
char my_stream[800];
iResult = recv(clntSocket,my_stream,sizeof(my_stream),0);
if(iResult<0)
{
int a = WSAGetLastError();
//Receives 10038 - WSAENOTSOCK
}
} while( iResult > 0 );
}
And I would sometimes (occasionally) get 10038. Which states that
Socket operation on nonsocket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket,or for select, a member of an fd_set was not valid.
Am I doing something wrong while setting up the socket ? Any suggestions on how to fix the problem ?
Either:
You never opened the socket.
You have corrupted the handle value.
You have closed the socket and then continued to use it.
I have python program which works perfectly for internet chatting. But program built on similar sockets in C++ do not work over internet.
Python program
import thread
import socket
class p2p:
def __init__(self):
socket.setdefaulttimeout(50)
self.port = 3000
#Destination IP HERE
self.peerId = '59.95.18.156'
#declaring sender socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM )
self.socket.bind(('', self.port))
self.socket.settimeout(50)
#starting thread for reception
thread.start_new_thread(self.receiveData, ())
while 1:
data=raw_input('>')
#print 'sending...'+data
self.sendData(data)
def receiveData(self):
while 1:
data,address=self.socket.recvfrom(1024)
print data
def sendData(self,data):
self.socket.sendto(data, (self.peerId,self.port))
if __name__=='__main__':
print 'Started......'
p2p()
I want to built similar functionality in c++. I took server and client programs from MSDN. But they are working only on localhost not over internet ..
they are as follows...
Sender
#include <stdio.h>
#include "winsock2.h"
void main() {
WSADATA wsaData;
SOCKET SendSocket;
sockaddr_in RecvAddr;
int Port = 3000;
char SendBuf[3]={'a','2','\0'};
int BufLen = 3;
//---------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//---------------------------------------------
// Create a socket for sending data
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//---------------------------------------------
// Set up the RecvAddr structure with the IP address of
// the receiver (in this example case "123.456.789.1")
// and the specified port number.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("59.95.18.156");
//---------------------------------------------
// Send a datagram to the receiver
printf("Sending a datagram to the receiver...\n");
sendto(SendSocket,
SendBuf,
BufLen,
0,
(SOCKADDR *) &RecvAddr,
sizeof(RecvAddr));
//---------------------------------------------
// When the application is finished sending, close the socket.
printf("Finished sending. Closing socket.\n");
closesocket(SendSocket);
//---------------------------------------------
// Clean up and quit.
printf("Exiting.\n");
WSACleanup();
return;
}
Receiver
#include <stdio.h>
#include "winsock2.h"
#include<iostream>
using namespace std;
void main() {
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
int Port = 3000;
char RecvBuf[3];
int BufLen = 3;
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof(SenderAddr);
//-----------------------------------------------
// Initialize Winsock
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
printf("Receiving datagrams...\n");
while(true){
recvfrom(RecvSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
cout<<RecvBuf;
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
printf("Finished receiving. Closing socket.\n");
closesocket(RecvSocket);
//-----------------------------------------------
// Clean up and exit.
printf("Exiting.\n");
WSACleanup();
return;
}
Thank you very much for any help ..
Sorry for too much code in the question.
Per the docs, sendto returns a number that's >0 (number of bytes sent) for success, <0 for failure, and in the latter case you use WSAGetLastError for more information. So try saving the sendto result, printing it (as well as the size of the data you're trying to send), and in case of error print the last-error code too. What do you see then?