I got trouble on using sendto() function in socket
int main(int argc, const char * argv[]) {
int acceptFd;
struct sockaddr_in servaddr, cliaddr;
char recieveBuf[512];
char sendBuf[512];
socklen_t cliLen;
if(-1 == (acceptFd = socket(AF_INET,SOCK_DGRAM,0))) perror("socket() failed.\n");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6789);
if(-1==bind(acceptFd,(struct sockaddr*)&servaddr,sizeof(servaddr))) perror("bind() failed.\n");
bzero(&cliaddr, sizeof(cliaddr));
while(1){
if(recvfrom(acceptFd, recieveBuf, 512, 0, (struct sockaddr*) &cliaddr, &cliLen) == -1) {
perror("recvfrom() failed");
continue;
}
strcpy(sendBuf,"recieved\n");
printf("%s\n",sendBuf);
if(-1 == sendto(acceptFd,sendBuf, 512,0,(struct sockaddr*)&cliaddr,cliLen)){
perror("sendto() failed");
continue;
}
}
}
the recvfrom() works fine, but every time sendto() was called, the error handling print out this: sendto() failed: Invalid argument
the send program is here:
#include "test.AcceptMessage.pb.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, const char * argv[]) {
int sendSocket;
struct sockaddr_in cliaddr;
char buf[512];
if(-1 == (sendSocket = socket(AF_INET,SOCK_DGRAM,0))) perror("socket() failed.\n");
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
cliaddr.sin_port = htons(6789);
sendto(sendSocket,buf, 512,0,(
struct sockaddr*)&cliaddr, sizeof(cliaddr));
recvfrom(sendSocket,buf,512,0, nullptr, nullptr);
printf("%s\n",buf);
return 0;
}
So what's wrong with this code?
From man recvfrom:
Before the call, it [addrlen] should be initialized to the size of the
buffer associated with src_addr.
Therefore, initialize your cliLen variable with:
socklen_t cliLen = sizeof(cliaddr);
You don't have any reason to use recvfrom() and sendto() at all here. It's a connected socket. Just use send() and recv().
Related
I'm having issues with my connect() method on the client side of my socket programming. I'm not sure if the issue is with my code or my method of running it. I'm running it in two seperate terminal windows - one for the server (which I'm running first) with the command './server 8080' and one for the client with the command './client 4 8080 hello'. When I run my code, the server program stops in the while loop just after the printf("this prints\n") line. I presume this means that it is waiting for a client to connect to it. The client program fails on the connect() call, and prints out my error message "Connection Failed". My code is posted below.
Server Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#define bufsize 1024
void eatZombies(int n){
wait3(NULL,WNOHANG,NULL); // Nom Nom
}
int main(int argc, char *argv[]){
int sock, length, msgsock, status;
struct sockaddr_in server;
pid_t id;
signal(SIGCHLD, &eatZombies);
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(atoi(argv[1])); // this time 1st arg is port#
if(bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Error binding the socket\n");
exit(0);
}
if(listen(server_fd, SOMAXCONN) < 0){
printf("Error listening for connections\n");
exit(0);
}
char buffer[1024] = {0};
char *hello = "Hello from server";
int addrlen = sizeof(server);
while(1){
printf("this prints\n");
int client_fd = accept(server_fd, (struct sockaddr *)&server, (socklen_t*)&addrlen);
printf("this doesnt\n");
if(client_fd < 0){
printf("Error accepting connection\n");
exit(0);
}
// the next call makes a new child process that will actually handle the client.
id = fork();
// when id == 0, this is the child and needs to do the work for the server.
// when if > 0, this is the parent, and it should just loop around,
// when id < 0, we had an error.
if(id > 0){
continue;
}
else if(id < 0){
printf("Error\n");
exit(0);
}
read(client_fd, buffer, 1024);
printf("%s\n", buffer);
write(client_fd, hello, strlen(hello), 0);
printf("Hello message sent\n");
exit(0);
}
return 0;
}
Client Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define bufsize 1024
int main(argc, argv) int argc; char *argv[];{
int sock, rval;
struct hostent *host;
struct sockaddr_in server; // not a pointer
char buf[bufsize];
printf("%d\n", argc);
if(argc != 4){
printf("usage:\ntcpclient hostname port string\n\n");
return(-1);
}
// look up hostname (server) using DNS
if ((host = gethostbyname(argv[1])) == 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
return(-1);
}
// Set up fields for socket to point to host and port
bcopy(host->h_addr, &server.sin_addr, host->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
// Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("Socket Creation Failed\n");
exit(0);
}
// connect (3-way handshake)
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Connection Failed\n");
exit(0);
}
// Copy the arg into buf so we can send it to the server
strncpy(buf, argv[3], bufsize);
// Send sentence to server
send(sock, buf, strlen(buf), 0);
printf("Message sent\n");
// read response from server
rval = read(sock, buf, bufsize);
// print result to window
fprintf(stdout,"%s\n", buf);
close(sock);
}
When running ./client 4 8080 hello, 4 is the host name. You meant to call ./client localhost 8080 hello.
So it was just a mistake in calling the application, not in the code.
I have written socket client code run fine with Linux GCC but through error on QNX platform. It through error as undefined reference to `socketpair'
compile command: aarch64-unknown-nto-qnx7.0.0-gcc ss1.c
Buid error
/tmp/cc8ssnim.o: In function `main':
ss1.c:(.text+0x34): undefined reference to `socketpair'
collect2: error: ld returned 1 exit status
Edited After john comment
Comiple time error fixed by adding -lsocket i get run time error as
setsockopt: Protocol not available
Example code taken from HERE
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include<iostream>
#include <sys/types.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char hello[500] = {};
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
ab:
std::cout<<"Enter send to client\n";
std::cin>>hello;
valread = read( new_socket , buffer, 1024);
printf("Received in server = %s\n",buffer );
memset( buffer, '\0', sizeof(char)*1024 );
send(new_socket , hello , strlen(hello) , 0 );
memset( hello, '\0', sizeof(char)*500 );
goto ab;
//printf("Hello message sent\n");
return 0;
}
I'm writing a C++ code that implements an UDP server and client.
The code works fine when I write two codes, one for the server and another for the client, as in this example : https://www.geeksforgeeks.org/udp-server-client-implementation-c/ .
What I'm trying to do is to write a client function and a server function in the same code. The ideia is that I select how the program is going to work with the command lines argument.
The problem is that, implementing this way and testing in two terminals running the same code, with different command line arguments, one for server and another for client, the client stucks in the recvfrom, when receiving the server response.
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXLINE 1024
#define PORT 32000
int send(){
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
socklen_t len;
int n;
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &cliaddr,
len);
printf("Hello message sent.\n");
return 0;
}
int receive(){
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int n;
socklen_t len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &servaddr,
&len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
return 0;
}
int main(int argc, char const *argv[]) {
int command = atoi(argv[1]);
if(command == 0){
send();
}
if(command == 1){
receive();
}
return 0;
}
The expected results is something like this, that i get when running the client and the server on separated codes:
Server side:
Hello from client
Hello message sent
Client side:
Hello message sent
Hello from server
But what I get when running the code above is
Server side:
Hello from client
Hello message sent
Client side:
Hello message sent
---gets stucked here---
What am i doing wrong?
In your send() function, you are not initializing len to the length of the buffer where recvfrom can store the client address.
According to the man page for recvfrom:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
If src_addr is not NULL, and the underlying protocol provides the
source address of the message, that source address is placed in the
buffer pointed to by src_addr. In this case, addrlen is a value-result
argument. Before the call, it should be initialized to the size of the
buffer associated with src_addr. Upon return, addrlen is updated to
contain the actual size of the source address.
It's not working because the client address isn't being properly received so the response message is being sent to the wrong address. To resolve your problem, you just need to initialize len before the call to recvfrom:
socklen_t len = sizeof(cliaddr); // The size of the buffer you're passing to store the client address
I am trying to get a very basic hello world UDP sender and UDP multicast listener to work. I have a PC but have a virtual machine with the Linux OS CentOS. It has no problems connecting to the internet. The sender and listener are two separate programs, Eclipse is my environment.
The Sender...
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define UDP_PORT 5403
#define UDP_GROUP "225.0.0.1" // 127.0.0.1
int main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd;
struct ip_mreq mreq;
char *message="Hello, World!";
int message_size = strlen(message) + 1;
// Create a UDP socket
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket(...) ");
return -1;
}
// allow multiple sockets to use the same PORT number
u_int reuse_port = 1;
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &reuse_port, sizeof(reuse_port)) < 0)
{
perror("setsockopt(...) ");
return -1;
}
// set up destination address
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(UDP_GROUP);
addr.sin_port = htons(UDP_PORT);
printf("Begin sendto(...) infinite loop\n");
while (true)
{
printf("Sending message: %s, of size: %d\n", message, message_size);
if (sendto(fd, message, message_size, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("sendto(...): ");
return -1;
}
// printf("message sent: %s\n", message);
sleep(1);
}
return 1;
}
The Listener...
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define UDP_PORT 5403
#define UDP_GROUP "225.0.0.1"
#define MAX_BUFFER_SIZE 256
int main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd, nbytes;
socklen_t addrlen;
struct ip_mreq mreq;
char msgbuf[MAX_BUFFER_SIZE];
u_int reuse_port = 1;
// Create a socket
fd = socket(AF_INET,SOCK_DGRAM,0);
if (fd < 0)
{
perror("create socket failed");
return -1;
}
// allow multiple sockets to use the same PORT number
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_port, sizeof(reuse_port)) < 0)
{
perror("Reusing port number failed");
return -1;
}
// set up destination address
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(UDP_PORT);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
return -1;
}
// Set the recvfrom timeout after 1 s
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
perror("Error setting recvfrom timeout\n");
return -1;
}
// use setsockopt() to request that the kernel join a multicast group
mreq.imr_multiaddr.s_addr = inet_addr(UDP_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
perror("setsockopt");
return -1;
}
addrlen = sizeof(addr);
printf("Begin recvfrom(...) infinite loop\n");
while (true)
{
nbytes = recvfrom(fd, msgbuf, MAX_BUFFER_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
if (nbytes < 0)
{
printf("recvfrom timeout\n");
}
else
{
printf("message received: %s\n", msgbuf);
}
}
return 1;
}
Every second, the sender program printf's "Sending message: Hello, World!, of size: 14" and every two seconds the receiver printf's "recvfrom timeout". I have set Wireshark to look at UDP traffic and I definitely see the sento data. The recvfrom is not getting any data. I have tried using many different Group IP's from 255.0.0.0 to 239.255.255.255, no change. I have tried many different ports, no change. Is their a special setup I need to do on my network card? I'm not sure what else to do. Small edit, the recvfrom and sendto message should not have "&".
For a project i need to send a UDP broadcast every second to 87.255.255.255 and port 4448 with the values of my project. I have writen some code in c++ but i got always the error:
Assertion `::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1' failed
with this line:
//assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1);
When i delete this line the code runs but i find nothing on wireshark.
Does anyone have a solution or some extra info to build a broadcast sender?
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <assert.h>
#include <string.h>
#include <ctime>
int main(int argc, char const *argv[]) {
sockaddr_in si_me, si_other;
int s;
printf("Making socket\n");
assert((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))!=-1);
fprintf(stderr,"usage %s hostname port\n", argv[0]);
int port=4448;
int broadcast=1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST,
&broadcast, sizeof broadcast);
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = INADDR_ANY;
assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr))!=-1);
while(1)
{
printf("Send message to broadcast\n");
char buf[10000];
strcpy(buf, "test for wireshark");
unsigned slen=sizeof(sockaddr);
send(s, buf, sizeof(buf)-1, 0);
//recvfrom(s, buf, sizeof(buf)-1, 0, (sockaddr *)&si_other, &slen);
printf("recv: %s\n", buf);
sleep(1);
}
}
Apparently there's some weirdness with broadcasting under UNIX. So this may or may not work as expected.
void errno_abort(const char* header)
{
perror(header);
exit(EXIT_FAILURE);
}
int main(int argc, char* argv[])
{
#define SERVERPORT 4567
struct sockaddr_in send_addr, recv_addr;
int trueflag = 1, count = 0;
int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
errno_abort("socket");
#ifndef RECV_ONLY
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
&trueflag, sizeof trueflag) < 0)
errno_abort("setsockopt");
memset(&send_addr, 0, sizeof send_addr);
send_addr.sin_family = AF_INET;
send_addr.sin_port = (in_port_t) htons(SERVERPORT);
// broadcasting address for unix (?)
inet_aton("127.255.255.255", &send_addr.sin_addr);
// send_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
#endif // ! RECV_ONLY
#ifndef SEND_ONLY
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
&trueflag, sizeof trueflag) < 0)
errno_abort("setsockopt");
memset(&recv_addr, 0, sizeof recv_addr);
recv_addr.sin_family = AF_INET;
recv_addr.sin_port = (in_port_t) htons(SERVERPORT);
recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr*) &recv_addr, sizeof recv_addr) < 0)
errno_abort("bind");
#endif // ! SEND_ONLY
while ( 1 ) {
#ifndef RECV_ONLY
char sbuf[256] = {};
snprintf(sbuf, sizeof(sbuf), "Hello(%d)!", count++);
if (sendto(fd, sbuf, strlen(sbuf)+1, 0,
(struct sockaddr*) &send_addr, sizeof send_addr) < 0)
errno_abort("send");
printf("send: %s\n", sbuf);
usleep(1000000/2);
#endif // ! RECV_ONLY
#ifndef SEND_ONLY
char rbuf[256] = {};
if (recv(fd, rbuf, sizeof(rbuf)-1, 0) < 0)
errno_abort("recv");
printf("recv: %s\n", rbuf);
#endif // ! SEND_ONLY
}
close(fd);
return 0;
}
Hope this helps. Good luck.
Sending a UDP packet with size 10000 is probably a bad idea.
Try using strlen(buffer) instead when calling send(). This might be a reason why you don't see anything on shark.
To find a reason why bind() fails, you need to eval errno.
BTW: I remember one TCP stack implementation, which did not like IPPROTO_UDP as third parameter to the socket() call even though it is supposed to work according to the standard. Try using 0 instead.