I have two programs, on is server and only listening and the client is talking. I send 1mbytes of data in chunks of 64bytes each. I will get the first chunk of 64byte but then my server exits because it failed to get other data. My client is sending all of the data.
void ServerLinux::Receive(){
int sock = 0;
struct sockaddr_in server;
char buffer[this->packageLength];
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
this->Die("Failed to create socket");
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(this->port);
if(bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0){
this->Die("Failed to bind the server socket");
}
if(listen(sock, 1) < 0){
this->Die("Failed to listen on server socket");
}
int clientSocket = 0;
struct sockaddr_in client;
socklen_t size = sizeof(client);
if((clientSocket = accept(sock, (struct sockaddr *) &client, &size)) < 0){
this->Die("Failed to accept client");
}
int received = -1;
//This is fine data is recived
if((received = recv(clientSocket, buffer, this->packageLength,0)) < 0){
this->Die("Failed to receive initial bytes from client");
}
std::cout << "Received!" << std::endl;
//Data is not received in this while loop
while(received > 0){
if((received = recv(sock, buffer, this->packageLength,0)) < 0){
this->Die("Failed to receive additional bytes frin client");
}
std::cout << "Received!" << std::endl;
}
}
Why don't you use the same arguments for recv?
works: recv(clientSocket, buffer, this->packageLength,0)
doesn't work recv(sock, buffer, this->packageLength,0)
Change sock to clientSocket.
Related
I am trying to build a UDP file transfer system with C++ that will allow the client to send four characters of a text file to the server at a time. The server will then take the four characters and add them to a new file on the server. I am confused on how to actually implement this. I know that a loop of some kind will have to be created on the client and server to continuously send data from the client and receive data on the server I just don't know how to implement it. I will post the code that I have so far for the client and server below. Any help is appreciated!
Client Code
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return 1;
}
// Get host IP address
s = gethostbyname(argv[1]);
// Setting destination info
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);
// File manipulation
fp = fopen(file.c_str(), "r");
while (c != EOF) {
c = fgetc(fp);
fileString += c;
charCounter++;
}
fclose(fp);
// UDP file transfer
socklen_t slen = sizeof(server);
memset(payload, 0, sizeof(payload));
strcpy(payload, dataBuffer.c_str());
sendRes = sendto(udpsocket, payload, 512, 0, (struct sockaddr *) &server, slen);
if (sendRes == -1) {
cerr << "Could not send to server";
return 1;
}
close(udpsocket);
return 0;
Server Code
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return -1;
}
// Receive data
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(udpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
cerr << "Can't bind to IP/Port";
return -2;
}
clen = sizeof(client);
memset(payload, 0, sizeof(payload));
recvfrom(udpsocket, payload, 512, 0, (sockaddr*)&client, &clen);
cout << "Payload: " << payload << "\n";
close(udpsocket);
return 0;
}
I am trying to send a broadcast UDP package to all my Lifx devices (wifi lamps). The devices should answer with another package to the same port I sent the first package from.
I am so far, that I see my sent broadcast package in wireshark. I also see the reply from the Lifx lamp.
But my program is stuck on recvfrom.
int sockfd;
struct sockaddr_in saddr_send, saddr_recv;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
int one = 1;
if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
memset(&saddr_send, 0, sizeof(saddr_send));
memset(&saddr_recv, 0, sizeof(saddr_recv));
// Filling dest information
saddr_send.sin_family = AF_INET; // IPv4
saddr_send.sin_addr.s_addr = INADDR_BROADCAST;
saddr_send.sin_port = htons(PORT);
// Filling source information
saddr_recv.sin_family = AF_INET; // IPv4
saddr_recv.sin_addr.s_addr = INADDR_ANY;
saddr_recv.sin_port = htons(PORT);
// Bind the socket with the server address
if (bind(sockfd, (const struct sockaddr *)&saddr_recv, sizeof(saddr_recv)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
char buffer[BUFF_SIZE];
size_t length;
unsigned size = sizeof(saddr_recv);
char recvbuffer[BUFF_SIZE];
length = sendMessage->getEncodedHeader(buffer, BUFF_SIZE);
int e = sendto(sockfd, buffer, length, 0, (struct sockaddr*) &saddr_send, sizeof(saddr_send));
if (e < 0) {
printf("%i\n", errno);
perror("Send error: ");
}
unsigned int r = recvfrom(sockfd, (void*)&recvbuffer, sizeof(recvbuffer), 0, (struct sockaddr*)&saddr_recv, &size);
if (r < sizeof(lifx_protocol_header)) {
printf("package too short");
}
close(sockfd);
I am not sure if I made a conceptional mistake or if I am to slow with calling recvfrom.
Any idea on additional points I could try to solve my problem?
I am working on a C++ UDP program, that sends a string to another client and should receive an answer.
Sending works fine, but i cant receive any packets. I looked with wireshark and my computer receives the packet at the right port and from the right IP, but my program seems to ignore them.
Do you have any idea?
int startWinsock(void);
int main()
{
long receive;
SOCKET sock;
char buffer[256];
SOCKADDR_IN si_me;
SOCKADDR_IN si_other;
///////////// Start Winsock ///////////////
receive = startWinsock();
if (receive != 0)
{
printf("Error: startWinsock, error code: %d\n", receive);
return 1;
}
else
{
printf("Winsock started!\n");
}
//////////// Create UDP Socket //////////////
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
{
printf("Fehler: Socket could not be created, errorcode: %d\n", WSAGetLastError());
return 1;
}
else
{
printf("UDP Socket created!\n");
}
si_me.sin_family = AF_INET;
si_me.sin_port = htons(1198);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
si_other.sin_family = AF_INET;
si_other.sin_port = htons(2000);
si_other.sin_addr.s_addr = inet_addr("10.2.134.10");
receive = connect(sock, (SOCKADDR*)&si_other, sizeof(SOCKADDR));
if (receive == SOCKET_ERROR)
{
cout << "Error : Connection Failed, Errorcode: " << WSAGetLastError() << endl;
}
else
{
cout << "Connected to" << si_other.sin_addr.s_addr << endl;
}
static int timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
// char broadcast = 1;
// setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
while (1)
{
printf("Insert Text: ");
gets(buffer);
//rc = sendto(s, buf, strlen(buf), 0, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
receive = send(sock, buffer, strlen(buffer), 0);
if (receive == SOCKET_ERROR)
{
//printf("error: sendto, error code: %d\n",WSAGetLastError());
printf("Error: send, error code: %d\n", WSAGetLastError());
//return 1;
}
else
{
printf("%d bytes sent!\n", receive);
}
static int timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
int wait = 0;
while (wait == 0)
{
//rc = recvfrom(s, buf, 256, 0, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
receive = recv(sock, buffer, sizeof(buffer), 0);
if (receive == SOCKET_ERROR)
{
//printf("Fehler: recvfrom, fehler code: %d\n",WSAGetLastError());
printf("Fehler: recv, fehler code: %d\n", WSAGetLastError());
//return 1;
}
else
{
wait = 1;
printf("%d bytes received!\n", receive);
buffer[receive] = '\0';
printf("Received: %s\n", buffer);
}
}
}
getchar();
return 0;
}
int startWinsock(void)
{
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 0), &wsa);
}
To make it so your code works nearly as-is by sending to itself, do the following:
change the "me" port to match "other"... si_me.sin_port = htons( 2000 );
bind to it... bind( sock, (SOCKADDR*)&si_me, sizeof( SOCKADDR ) ); just before connect
As UDP is Datagram-Oriented and connectionless, you need to use recvfrom/sento instead of recv/send. Also the receivetimeout should be set with at timeval.
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
I want to receive UDP packets from a server application (on the same computer) and forward it to an UDP receive app on a different port.
The server app is not mine, nor do i have the source code.
The UDP receive app is a Java application.
If i bind the Java application directly to the server app port, there is very low latency, but if i connect it to the relay appĀ“port i get almost one second of delay.
The receiving port has to be non-blocking.
#define rcv_length 160
fd_set fds;
int n;
struct timeval tv;
void CMClient::startUDPListener(){
CMport_number = 32200;
remoteAddrLen = sizeof(struct sockaddr_in);
if (WSAStartup(0x0101, &CMw) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
CMsd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (CMsd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
CMserver.sin_family = AF_INET;
CMserver.sin_port = htons(CMport_number);
CMserver.sin_addr.s_addr = inet_addr("127.0.0.1");
long rc=bind(CMsd,(SOCKADDR*)&CMserver,sizeof(SOCKADDR_IN));
if(rc==SOCKET_ERROR)
{
printf("Error: bind code: %d\n",WSAGetLastError());
}
}
void CMClient::updateData(UDPServer* svr, int CMnr){
FD_ZERO(&fds);
FD_SET(CMsd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 1;
n = select ( CMsd, &fds, NULL, NULL, &tv ) ;
if (FD_ISSET(CMsd, &fds))
{
FD_CLR(CMsd,&fds);
char* rcvBuffer = new char[rcv_length];
long rc=recv(CMsd,rcvBuffer,rcv_length,0); //receive
if(rc!=SOCKET_ERROR)
{
rcvBuffer[0] = CMnr;
sendto(svr->sd, (char*)rcvBuffer, rcv_length, 0, (struct sockaddr*)&svr->server, sizeof(svr->server)) != (int)sizeof(rcvBuffer); //send
}
if(rcvBuffer)
delete [] rcvBuffer;
}
}
The UDP server to send to the Java application is initialized as follows:
void UDPServer::startUDPServer(){
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
server.sin_family = AF_INET;
server.sin_port = htons(port_number);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Could not connect name to socket.\n");
stopUDPServer();
}
}
The main calls
UDPServer* udpsvr;
udpsvr = new UDPServer;
udpsvr->startUDPServer();
while(1){
CM->updateData(udpsvr, CMid);
}
Any help would be appreciated why i get that much delay.
The data received from the Java app is correct but ~1 second delay.
Thank you,
Regards
Don't use bind() on client. Use connect().
Summing up, for UDP:
Server:
socket()
bind()
Client:
socket()
connect()
Example of code for server:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
Example of code for client:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
Finally, you may want to have a look at flushing UDP buffers.
I've bumped into a problem with my broadcasting server. basically, I want it to send broadcasts continuously from the moment I launch it. for some reason it will not start until it receives a connection from somewhere. I must have messed up something but I can't realise what.
here is my code:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET sock;
sock = socket(AF_INET, SOCK_DGRAM, 0);
char broadcast = 'a';
if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0)
{
perror("broadcast options");
closesocket(sock);
return 1;
}
struct sockaddr_in Recv_addr;
struct sockaddr_in Sender_addr;
int len = sizeof(struct sockaddr_in);
char recvBuff[50];
int recvBuffLen = 50;
//char sendMsg[] = "broadcast message from salam rofl";
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
{
perror("bind");
_getch;
closesocket(sock);
return 1;
}
//recvfrom(sock, recvBuff, recvBuffLen, 0, (sockaddr *)&Sender_addr, &len);
//cout << "\nreceived message: " << recvBuff;
while(1)
{
Sleep(3000);
//_getch();
getTime();
if(sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
{
perror("borhot send: ");
_getch();
closesocket(sock);
return 0;
}
else cout << "message sent successfully";
}
_getch;
closesocket(sock);
WSACleanup();
return 0;
basically if I remove recvfrom, it will give me a send error ("No error") which simply puzzles me. also, if I send it something with a client, it will start broadcasting, but if I connect with another client, only the first client is receiving the broadcast.
thank you in advance.
I doubt it matters but I'm trying to broadcast the current time.
You are not initializing Sender_Addr so you are not telling sendto() where to actually broadcast to.
Try this instead:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET)
{
perror("socket creation");
_getch;
return 1;
}
BOOL enabled = TRUE;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&enabled, sizeof(BOOL)) < 0)
{
perror("broadcast options");
_getch;
closesocket(sock);
return 1;
}
struct sockaddr_in Sender_addr;
Sender_addr.sin_family = AF_INET;
Sender_addr.sin_port = htons(BROADCAST_PORT);
Sender_addr.sin_addr.s_addr = inet_addr("Broadcast IP Here");
struct sockaddr_in Recv_addr;
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
{
perror("bind");
_getch;
closesocket(sock);
return 1;
}
while(1)
{
Sleep(3000);
getTime();
if (sendto(sock, currentTime, strlen(currentTime)+1, 0, (sockaddr *)&Sender_addr, sizeof(Sender_addr)) < 0)
{
perror("borhot send: ");
_getch();
closesocket(sock);
return 0;
}
cout << "message sent successfully";
}
_getch;
closesocket(sock);
WSACleanup();
return 0;
Looks like your Sender_addr is never being initialized, thus when you remove the recvfrom you're getting an error, and when the recvfrom is in place it's getting populated with the address of the first client to connect (but never being updated).
If you don't know the addresses of the clients that you want to broadcast to, you'll need to setup some handshake where they send you a ping, you receive it with recvfrom, and you store their address in a list or something. Then, when you broadcast, you need to send your message to every client address in the list.