When I try to send some basic UDP message it looks like it doesn't send it.
I tried to run couple of examples that I found online.
I am using SocketTest v3.0.0 for testing server/client.
When I tested TCP sending everything worked as expected, but I UDP case it simply doesn't.
Can you provide some really basic UDP send code snippet ?
For example the receiver will be on localhost and the message will contain "test" and it will be fixed length ?
And I have one more small question. It I send the message on local host can the application(server) itself receive it and think that someone else has send it (causing looping) because it does not connect to some peer it just send the message and listen on same ip-port ?
Thanks :)
You have a lot of usefull examples here: https://nikhilm.github.io/uvbook/networking.html
uv_loop_t *loop;
uv_udp_t send_socket;
uv_udp_t recv_socket;
int main() {
loop = uv_default_loop();
uv_udp_init(loop, &recv_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", 68, &recv_addr);
uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);
uv_udp_init(loop, &send_socket);
struct sockaddr_in broadcast_addr;
uv_ip4_addr("0.0.0.0", 0, &broadcast_addr);
uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0);
uv_udp_set_broadcast(&send_socket, 1);
uv_udp_send_t send_req;
uv_buf_t discover_msg = make_discover_msg();
struct sockaddr_in send_addr;
uv_ip4_addr("255.255.255.255", 67, &send_addr);
uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send);
return uv_run(loop, UV_RUN_DEFAULT);
}
Here is a basic example that shows sending UDP packets and receiving the response from the other side:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
uv_udp_t udp_socket;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
void on_read(uv_udp_t *socket, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags){
if (nread < 0) {
fprintf(stderr, "read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) socket, NULL);
} else if (nread > 0) {
char sender[17] = { 0 };
uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
printf("recv from %s:%.*s\n", sender, (int)buf->len, buf->base);
}
if (buf && buf->base) {
/* releases the buffer allocated on alloc_buffer() */
free(buf->base);
}
}
void on_send(uv_udp_send_t *req, int status) {
if (status) {
fprintf(stderr, "send error %s\n", uv_strerror(status));
}
/* releases the request allocated on send_msg() */
if (req) free(req);
}
void send_msg(char *msg){
uv_buf_t buf = uv_buf_init(msg, strlen(msg)+1);
struct sockaddr_in send_addr;
uv_ip4_addr("123.45.67.89", 2222, &send_addr);
uv_udp_send_t *send_req = malloc(sizeof(uv_udp_send_t));
uv_udp_send(send_req, &udp_socket, &buf, 1, (const struct sockaddr *)&send_addr, on_send);
}
int main() {
uv_loop_t *loop = uv_default_loop();
uv_udp_init(loop, &udp_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", 2345, &recv_addr);
uv_udp_bind(&udp_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
uv_udp_recv_start(&udp_socket, alloc_buffer, on_read);
send_msg("hi there!");
send_msg("hello world");
return uv_run(loop, UV_RUN_DEFAULT);
}
You may try stream route handler, although is new, but it's reliable and had tested with heavy traffic data transaction.
Example
void read_data(srh_request_t *req);
void read_data(srh_request_t *req) {
char *a = "CAUSE ERROR FREE INVALID";
if (strncmp( (char*)req->in_buff->start, "ERROR", 5) == 0) {
free(a);
}
// printf("%d, %.*s\n", i++, (int) (req->in_buff->end - req->in_buff->start), req->in_buff->start);
srh_write_output_buffer_l(req, req->in_buff->start, (req->in_buff->end - req->in_buff->start));
// printf("%d, %.*s\n", i++, (int) (req->out_buff->end - req->out_buff->start), req->out_buff->start);
}
int main(void) {
srh_instance_t * instance = srh_create_routing_instance(24, NULL, NULL);
srh_add_udp_fd(instance, 12345, read_data, 1024, NULL);
srh_add_tcp_fd(instance, 3232, read_data, 64, NULL);
srh_start(instance, 1);
return 0;
}
Related
I am running a sample libevent based server, however, sometimes, this server will immediately send a TCP FIN immediately after TCP handshake according to wireshark capture. The server didn't crash. The OS is ubuntu 18.04, the terminal has ulimit -n being 100000.
Any idea why?
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int printed = 0;
static void echo_read_cb(struct bufferevent *bev, void *ctx) {
/* This callback is invoked when there is data to read on bev. */
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev);
//evbuffer_add_buffer(output, input); //if I replace the next line with this, same issue of unexpected server side closure on some sockets
evbuffer_add(bufferevent_get_output(bev), "a", 1);
}
static void echo_event_cb(struct bufferevent *bev, short events, void *ctx) {
if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
int fd = bufferevent_getfd(bev);
evutil_closesocket(fd);
bufferevent_free(bev);
return;
}
}
static void
accept_conn_cb(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *address, int socklen,
void *ctx)
{
/* We got a new connection! Set up a bufferevent for it. */
struct event_base *base = evconnlistener_get_base(listener);
struct bufferevent *bev = bufferevent_socket_new(
base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL);
bufferevent_enable(bev, EV_READ|EV_WRITE);
}
static void
accept_error_cb(struct evconnlistener *listener, void *ctx)
{
struct event_base *base = evconnlistener_get_base(listener);
int err = EVUTIL_SOCKET_ERROR();
fprintf(stderr, "Got an error %d (%s) on the listener. "
"Shutting down.\n", err, evutil_socket_error_to_string(err));
event_base_loopexit(base, NULL);
}
int
main(int argc, char **argv)
{
struct event_base *base;
struct evconnlistener *listener;
struct sockaddr_in sin;
int port = 9876;
if (argc > 1) {
port = atoi(argv[1]);
}
if (port<=0 || port>65535) {
puts("Invalid port");
return 1;
}
base = event_base_new();
if (!base) {
puts("Couldn't open event base");
return 1;
}
/* Clear the sockaddr before using it, in case there are extra
* platform-specific fields that can mess us up. */
memset(&sin, 0, sizeof(sin));
/* This is an INET address */
sin.sin_family = AF_INET;
/* Listen on 0.0.0.0 */
sin.sin_addr.s_addr = htonl(0);
/* Listen on the given port. */
sin.sin_port = htons(port);
listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 10000,
(struct sockaddr*)&sin, sizeof(sin));
if (!listener) {
perror("Couldn't create listener");
return 1;
}
evconnlistener_set_error_cb(listener, accept_error_cb);
event_base_dispatch(base);
return 0;
}
Turned out there is no need to have evutil_closesocket(fd) in the function echo_event_cb. It's wrong to have it since it will result in a double-free.
As to why the server program didn't crash, that's a miracle :-)
i am having an issue when i start listening from incoming messages,
server is stuck on uv_run, i had the server working but deleted the
file with the wrong file on compilation and now i am stuck =/
i am using libuv library and trying to make an echo server udp based
#define UDP_SERVER_PORT 8888
static void on_send(uv_udp_send_t* req, int status){
free(req);
if (status) {
fprintf(stderr, "uv_udp_send_cb error: %s\n", uv_strerror(status));
}
}
static void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf,const struct sockaddr *addr,unsigned flags){
puts(":::::ON READ::::::");
(void)flags;
if (nread < 0) {
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
uv_close((uv_handle_t*) req, NULL);
free(buf->base);
return;
}
if (nread > 0) {
char sender[17] = { 0 };
uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
fprintf(stderr, "Recv from %s\n", sender);
uv_udp_send_t* res = malloc(sizeof(uv_udp_send_t));
uv_buf_t buff = uv_buf_init(buf->base, nread);
printf("-> Message Received:\n- %s\n", buf->base);
uv_udp_send(res, req, &buff, 1, addr, on_send);
}
free(buf->base);
}
static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf){
puts(":::::ALLOC BUFFER::::::");
(void)handle;
buf->base = malloc(suggested_size);
bzero(buf->base , suggested_size);
buf->len = suggested_size;
}
uv_udp_t* init_echo_udp_server(uv_loop_t *loop, const char* address, int port){
puts(":::::INIT ECHO SERVER::::::");
uv_udp_t *recv_socket = malloc(sizeof(uv_udp_t));
struct sockaddr_in recv_addr;
uv_ip4_addr(address, port, &recv_addr);
uv_udp_init(loop, recv_socket);
puts(":::::bind::::::");
uv_udp_bind(recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
puts(":::::start::::::");
uv_udp_recv_start(recv_socket, alloc_buffer, on_read);
return recv_socket;
}
uv_loop_t *loop= 0;
int main(int argc, const char** argv){
loop = uv_default_loop();
uv_udp_t* udp_socket = init_echo_udp_server(loop, "0.0.0.0", UDP_SERVER_PORT);
printf("----- SERVER LISTENING -----\n");
printf("-> UDP port: %d\n", UDP_SERVER_PORT);
uv_run(loop, UV_RUN_DEFAULT);
}
I'm trying to write tic-tack-toe game communicates through UDP.
For now I have code:
int recv_txt(int sock, struct sockaddr_in *incoming_addr)
{
char bud[MAX_LENGTH];
unsigned int incoming_add_len;
incoming_add_len = sizeof(*incoming_addr);
if(recvfrom(sock, &buf, MAX_LENGTH, 0 (struct sockaddr*)incoming_addr, &incoming_addr_len) < 0)
{
return 0;
}
printf("received %s", buf);
return 1;
}
int main(int argv, char **argc)
{
/** some code to create socket etc */
struct sockaddr_in incoming_addr;
for(;;)
{
recv_txt(sock, &incoming_addr);
//here I would like to create new thread, which will process the buffer from recv_txt and send response;
}
}
and now I need to get buffer from recv_txt, put it inside structure like this:
struct M_s
{
struct sockaddr_in address;
char[MAX_LENGTH] buffer;
}
and pass it to new thread. But I can't get the buffer from recv_txt. Im pretty new in C and for now i can't work with pointers very well.
Thanks for any advice.
EDIT
I tried solution provided by Frankie_c, but I have problem with printf now.
When I try in main:
LP_ARGS_STRUCT args = recv_txt(sock)
printf("data from: %s", inet_ntoa(args->address.sin_adrr))
i don't get any print to console or get error message.
EDIT2 - full code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SRV_PORT 23456
#define MAX_TXT_LENGTH 1000
#define MAX_ROOMS 1
int sock;
typedef struct args_s
{
struct sockaddr_in address;
char buffer[MAX_TXT_LENGTH];
} ARGS_STRUCT, *LP_ARGS_STRUCT;
//typedef struct args_s args;
LP_ARGS_STRUCT recv_txt(int sock)
{
LP_ARGS_STRUCT args = malloc(sizeof(ARGS_STRUCT));
//memory error
if(!args)
{
return 1;
}
unsigned int incoming_addr_len = sizeof(args->address);
//incoming_addr_len = sizeof(*incoming_addr);
if (recvfrom(sock, &args->buffer, MAX_TXT_LENGTH, 0,
(struct sockaddr*)&args->address, &incoming_addr_len) < 0)
{
free(args);
return NULL;
}
printf("received: %s %s\n", args->buffer, inet_ntoa(args->address.sin_addr));
return 1;
}
int main(int argv, char **argc)
{
int i = 0;
int optval;
struct sockaddr_in addr, incoming_addr;
char buffer[MAX_TXT_LENGTH];
/* create socket */
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
{
err("socket()");
}
/* set reusable flag */
optval = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
/* prepare inet address */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(SRV_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY); /* listen on all interfaces */
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
err("bind");
}
for(;;)
{
LP_ARGS_STRUCT args = recv_txt(sock);
if(!args) continue;
printf("%s\n", args->buffer);
}
return 0;
}
and after receiving a packet I get:
received: Hello 192.168.56.1
Segmentation fault (code dumped)
Process returned 139 (0x8B)
For the original question try this:
typedef struct M_s
{
struct sockaddr_in address;
char[MAX_LENGTH] buffer;
} M_STRUCT, *LP_M_STRUCT; //Create a typedef for struct
//Modify your function to return a structure pointer and having just socket as par...
LP_M_STRUCT recv_txt(int sock)
{
LP_M_STRUCT pMs = malloc(sizeof(M_STRUCT));
if (!pMs)
{
//Handle memory error here!
return NULL;
}
unsigned int incoming_add_len = sizeof(pMs->incoming_addr);
if (recvfrom(sock, &pMs->buffer, MAX_LENGTH, 0, (struct sockaddr *)&pMs->incoming_addr, &incoming_addr_len) < 0)
{
free(pMs); //Release memory
return NULL; //Return nothing...
}
//If we are here we were successfull.
//The structure pMs holds all data we need... so give it to caller...
printf("From %s received %s", inet_ntoa(pMs->address.sin_addr), pMs->buffer);
return pMs;
}
int main(int argv, char **argc)
{
/** some code to create socket etc */
for (;;)
{
LP_M_STRUCT pMs = recv_txt(sock);
if (!pMs) //Check if we get a sign of life on UDP...
continue; //No continue to wait for ...
//We print values again to check that it is ok...
printf("From %s received %s", inet_ntoa(pMs->address.sin_addr), pMs->buffer);
//here create new thread to process the buffer from recv_txt and send response;
//The new thread code have to release structure memory when done!!!
}
}
EDIT: Your problem is that you don't return the allocated structure when successfull and don't return NULL when fail. See:
LP_ARGS_STRUCT recv_txt(int sock)
{
LP_ARGS_STRUCT args = malloc(sizeof(ARGS_STRUCT));
//memory error
if(!args)
{
//return 1; !!!WRONG!!!
return NULL;
}
unsigned int incoming_addr_len = sizeof(args->address);
//incoming_addr_len = sizeof(*incoming_addr);
if (recvfrom(sock, &args->buffer, MAX_TXT_LENGTH, 0,
(struct sockaddr*)&args->address, &incoming_addr_len) < 0)
{
free(args);
return NULL;
}
printf("received: %s %s\n", args->buffer, inet_ntoa(args->address.sin_addr));
//return 1; WRONG! You have to return the allocated struct
return args;
}
I have two programs which communicate with each other.
Client: First send the message then listen for reply.
Server: Listen for reply and then send message.
Im able to send message from client prefectly and listen in server too. But problem comes when I try to send message from server.
struct hostent *gethostbyname();
typedef struct Message {
unsigned int length;
unsigned char data[SIZE];
} Message;
typedef struct sockaddr_in SocketAddress;
int fileDesc;
int aLength;
void main(int argc, char **argv) {
Message callMsg, rep;
aLength = 0;
SocketAddress clientSAMain, serverSAMain;
int port = RECIPIENT_PORT;
if ((fileDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
//return BAD;
}
makeReceiverSA(&serverSAMain, port);
if (bind(fileDesc, (struct sockaddr *) &serverSAMain,
sizeof(struct sockaddr_in)) != 0) {
perror("Bind failed\n");
close(fileDesc);
//return BAD;
}
clientSAMain.sin_family = AF_INET;
aLength = sizeof(serverSAMain);
GetRequest(&callMsg, port, &clientSAMain);
SendReply(&rep, port, clientSAMain);
close(fileDesc);
}
void GetRequest(Message *callMessage, int s, SocketAddress *clientSA) {
//SocketAddress serverSA;
int n;
int i;
if ((n = recvfrom(fileDesc, callMessage->data, SIZE, 0,
(struct sockaddr *) &clientSA, &aLength)) < 0)
perror("Receive 1");
else
printf("\n Received Message:(%s)length = %d \n", callMessage->data, n);
}
}
void SendReply(Message *replyMessage, int s, SocketAddress clientSANew) {
printf("Enter a reply:");
scanf("%s", replyMessage->data);
if ((n = sendto(fileDesc, replyMessage->data, sizeof(replyMessage->data), 0,
(struct sockaddr *) &clientSANew, sizeof(struct sockaddr_in))) < 0)
perror("Send Failed in Server\n");
if (n != strlen(replyMessage->data))
printf("sent %d\n", n + 1);
}
/* make a socket address using any of the addressses of this computer
for a local socket on given port */
void makeReceiverSA(struct sockaddr_in *sa, int port) {
sa->sin_family = AF_INET;
sa->sin_port = htons(port);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
//If i place the sendreply function code in GetRequest function it is working fine. Can anyone help me with this. I have been trying all the possible way but did not find a solution. Work under progress for me so spare me if it is silly question.
PS:Edited out all the unnecessary code.
recvfrom(fileDesc, callMessage->data, SIZE, 0,
(struct sockaddr *) &clientSA, &aLength)
Because clientSA is a pointer, the above will overwrite the pointer variable and the memory after it. &clientSA in the above call should be clientSA.
I've written a UDP send/receive function to send a struct and listen for another struct back. The bytes have to be sent in a particular order, but this is working OK as I'm using #pragma pack(1). The only problem that I'm having now is that if any Null values (0x00) appear in the struct, the rest of the data after the Null disappears.
I guess there's something fairly simple that I'm doing wrong, but here is my code:
typedef u_int8_t NN;
typedef u_int8_t X;
typedef int32_t S;
typedef u_int32_t U;
typedef char C;
typedef struct{
X test;
NN test2[2];
C test3[4];
S test4;
} Test;
int main(int argc, char** argv)
{
Test t;
memset( &t, 0, sizeof(t));
t.test = 0xde;
t.test2[0]=0xad; t.test2[1]=0x00;
t.test3[0]=0xbe; t.test3[1]=0xef; t.test3[2]=0xde; t.test3[3]=0xca;
t.test4=0xde;
LogOnResponse response;
udp_send_receive(&t, &response);
return 0;
}
And here is my send/receive function:
int send_and_receive(void* message, void* reply, int do_send, int expect_reply)
{
struct sockaddr_in serv_addr;
int sockfd, i, slen=sizeof(serv_addr);
int buflen = BUFLEN;
void* buf = NULL;
struct timeval tv;
int n_timeouts=1;
int recv_retval;
// printf("Message Size: %d\n", strlen(message));
if ( (strlen(message)) >= BUFLEN)
err("Message too big");
buf = malloc(buflen);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
tv.tv_sec = timeout_seconds;
tv.tv_usec = timeout_microseconds;
if( setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0 ){
err("Setting Timout");
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(IP_ADDRESS, &serv_addr.sin_addr)==0)
err("inet_aton() failed\n");
//---Timeout Send/Receive loop
do{
if(do_send == TRUE){
strcpy(buf, message);
if (sendto(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, slen)==-1)
err("sendto()");
}
if (expect_reply == TRUE){
if( (recv_retval = recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, &slen)) == -1){
itercount++;
}
}
}while ((itercount < itermax) && (recv_retval == -1));
if ( itercount != itermax ){
memcpy(reply, buf, BUFLEN);
}
else{
reply=NULL;
}
close(sockfd);
free(buf);
return 0;
}
void udp_send_receive(void* message, void* reply)
{
send_and_receive(message, reply, TRUE, TRUE);
}
Running the above code and capturing the packets with WireShark shows:
Data: DEAD000000000000000000....
I'd like it to show:
Data: DEAD00BEEFDECADE
I'd really appreciate some pointers on this.
You can't use string functions (like strlen or strcpy) for binary data. It's because strings are terminated by the value zero (character '\0').
For example, you use strcpy to copy data, but it will stop as soon as is sees the string terminator meaning it will not copy all of the data.
Rather than using strcpy use
void * memcpy ( void * destination, const void * source, size_t num );
Doing strcpy(buf, message); in send_and_receive() is incorrect. I would update code to pass size of message and use that to copy memory as
udp_send_receive(&t, sizeof(t), &response);
void udp_send_receive(void* message, int len, void* reply){
send_and_receive(message, len reply, TRUE, TRUE);
}
int send_and_receive(void* message, int len, void* reply, int do_send, int expect_reply){
...
int buflen = len;
....
memcpy(buf, message, len); //instead of strcpt(buf, message)
...
}