int main(void) { struct UDPsopa sopa = { .sop = NULL, .pap = NULL, .port = 0, // 0 = pick unused port .packet_size = 512, .packet_num = 0, .host_port = 4444 }; strcpy(sopa.host_name, "127.0.0.1"); if (udp_setup(&sopa) != 0) { udp_cleanup(&sopa); exit(EXIT_FAILURE); } // additional client setup if (SDLNet_ResolveHost(&(sopa.pap->address), sopa.host_name, sopa.host_port) != 0) { printf("SDLNet_ResolveHost(&(sopa.pap->address), sopa.host_name, sopa.host_port) != 0\n"); printf("SDLNet_GetError() = '%s'\n", SDLNet_GetError()); udp_cleanup(&sopa); exit(EXIT_FAILURE); } srand(123); for (;;) { sleep(1); // 1 second sprintf((char*)sopa.pap->data, "rand_num = %d", rand()); sopa.pap->len = strlen((char*)sopa.pap->data) + 1; const int channel = -1; // -1 = use packet's address as destination if (SDLNet_UDP_Send(sopa.sop, channel, sopa.pap) == 0) { printf("SDLNet_UDP_Send(sopa.sop, channel, sopa.pap) == 0\n"); printf("SDLNet_GetError() = '%s'\n", SDLNet_GetError()); udp_cleanup(&sopa); exit(EXIT_FAILURE); } switch (SDLNet_UDP_Recv(sopa.sop, sopa.pap)) { case -1: printf("SDLNet_UDP_Recv(sopa.sop, sopa.pap) == -1\n"); printf("SDLNet_GetError() = '%s'\n", SDLNet_GetError()); udp_cleanup(&sopa); exit(EXIT_FAILURE); case 0: printf("SDLNet_UDP_Recv(sopa.sop, sopa.pap) == 0 // no packets received\n"); break; case 1: sopa.packet_num++; udp_print(&sopa); break; } } // for(;;) udp_cleanup(&sopa); exit(EXIT_SUCCESS); }
void send_test(void) { u32 ip = ((u32)192 << 24) | ((u32)168 << 16) | ((u32)1 << 8) | 20; u16 src_port; u16 port = 8888; char data[] = "hello world!"; u16 len; udp_close(0); if (udp_setup(ip, port, port) < 0) err_log("udp_setup"); send_data(ip, port, port, data, strlen(data)); recv_data(&ip, &src_port, data_i, &len); }
int main(int argc, char **argv) { int udp_socket; int tcp_socket; int tcp_port; int client_socket; struct sockaddr_in addr; int addr_size; char buffer[1025]; struct client *clients; int num_clients; int max_clients; int i, j; int len; char* temp_str; fd_set read_fds_master; fd_set read_fds_copy; int fd_max; FD_ZERO(&read_fds_master); FD_ZERO(&read_fds_copy); clients = malloc(BACKLOG * sizeof(struct client)); num_clients = 0; max_clients = BACKLOG; /* signal(SIGINT, handle_sigint); */ if ((udp_socket = udp_setup(UDP_PORT)) == -1) exit(1); /* make udp socket "select()able" */ FD_SET(udp_socket, &read_fds_master); fd_max = udp_socket; if((tcp_socket = tcp_setup(&tcp_port)) == -1) exit(1); printf("Listening on tcp port: %d\n", tcp_port); /* make tcp socket "select()able" */ FD_SET(tcp_socket, &read_fds_master); fd_max = tcp_socket; /* main loop */ for (;;) { /* handle readable sockets */ read_fds_copy = read_fds_master; // make a copy that select() can modify if (select(fd_max + 1, &read_fds_copy, NULL, NULL, NULL) == -1) { fprintf(stderr, "Error during select().\n"); close(udp_socket); exit(1); } for (i = 0; i <= fd_max; i++) { if (FD_ISSET(i, &read_fds_copy)) { if (i == udp_socket) { /* answer a multicast message */ memset(buffer, 0, sizeof(buffer)); addr_size = sizeof(addr); if (recvfrom(udp_socket, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &addr_size) == -1) { fprintf(stderr, "Error receiving multicast message.\n"); close(udp_socket); exit(1); } if (strncmp(buffer, "server_discovery", 16) == 0) { printf("%s:%d - discovery request\n", inet_ntoa(addr.sin_addr.s_addr), ntohs(addr.sin_port)); len = sprintf(buffer, "discovery_reply %d\n", tcp_port); addr_size = sizeof(addr); if (sendto(udp_socket, buffer, len, 0, (struct sockaddr*)&addr, addr_size) == -1) { perror("Error answering multicast message.\n"); close(udp_socket); exit(1); } } } if (i == tcp_socket) { for (j = 0; j < num_clients; j++) { if (clients[j].status == 'd') break; /* the value of j at this point is used as a side effect later */ } /* j is now ALWAYS the first unused index of the clients array */ if (j == num_clients) num_clients++; if (num_clients > max_clients) { max_clients = max_clients + BACKLOG; clients = realloc(clients, max_clients * sizeof(struct client)); } addr_size = sizeof(addr); clients[j].socket = accept(tcp_socket, (struct sockaddr*)&addr, &addr_size); clients[j].status = 'c'; /* save source as string for logging and debugging */ strncpy(clients[j].socket_addr, (const char*)inet_ntoa(addr.sin_addr.s_addr), 15); clients[j].socket_port = ntohs(addr.sin_port); printf("%s:%d - new connection.\n", clients[j].socket_addr, clients[j].socket_port); FD_SET(clients[j].socket, &read_fds_master); if (clients[j].socket > fd_max) fd_max = clients[j].socket; } for (j = 0; j < num_clients; j++) { if (i == clients[j].socket) { memset(buffer, 0, sizeof(buffer)); len = recv(clients[j].socket, buffer, sizeof(buffer) - 1 - strlen(clients[j].line_buffer), 0); switch (len) { case 0: printf("%s:%d - disconnected.\n", clients[j].socket_addr, clients[j].socket_port); FD_CLR(clients[j].socket, &read_fds_master); clients[j].status = 'd'; push_global_filelist(clients, num_clients); break; case -1: /* TODO: handle gracefully. this is usually a "connection reset by peer" */ perror("recv"); break; default: strncat(clients[j].line_buffer, buffer, len); while (strchr(clients[j].line_buffer, '\n') != NULL) { switch (clients[j].status) { case 'c': //printf("status: connected\n"); if (sscanf(clients[j].line_buffer, "register %d", &(clients[j].download_port)) == 1) { printf("%s:%d - registered port %d for downloads.\n", clients[j].socket_addr, clients[j].socket_port, clients[j].download_port); clients[j].status = 'r'; break; } printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); break; case 'r': //printf("status: registered\n"); //printf("buffer: %s", clients[j].line_buffer); if (sscanf(clients[j].line_buffer, "send_filelist %d\n", &(clients[j].filelist_size)) == 1) { if (clients[j].filelist_size > 0) { printf("%s:%d - will send %d file list entries next.\n", clients[j].socket_addr, clients[j].socket_port, clients[j].filelist_size); if (clients[j].file_list != NULL) free(clients[j].file_list); clients[j].file_list = malloc(clients[j].filelist_size * sizeof(struct filelist_entry)); } clients[j].status = 's'; clients[j].filelist_len = 0; break; } if (strncmp(clients[j].line_buffer, "unregister", 10) == 0) { printf("%s:%d - unregistered download port.\n", clients[j].socket_addr, clients[j].socket_port); clients[j].status = 'c'; break; } printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); break; case 's': //printf("status: sending file list\n"); if (clients[j].filelist_len < clients[j].filelist_size) { len = clients[j].filelist_len; if (sscanf(clients[j].line_buffer , "%d %1000s", &(clients[j].file_list[len].size), clients[j].file_list[len].name) == 2) { clients[j].filelist_len = clients[j].filelist_len + 1; printf("%s:%d - sent a file list entry: %s (%d bytes)\n", clients[j].socket_addr, clients[j].socket_port, clients[j].file_list[len].name, clients[j].file_list[len].size); } else { printf("%s:%d - sent %d unrecognized bytes: %s\n", clients[j].socket_addr, clients[j].socket_port, strlen(clients[j].line_buffer), clients[j].line_buffer); } } if (clients[j].filelist_len == clients[j].filelist_size) { clients[j].status = 'r'; push_global_filelist(clients, num_clients); } break; default: break; } /* consume part of buffer */ temp_str = strchr(clients[j].line_buffer, '\n'); //printf("bytes left: %d\n", strlen(temp_str)); if (strlen(temp_str) > 1) { memset(buffer, 0, sizeof(buffer)); strncpy(buffer, temp_str + 1, strlen(temp_str) - 1); //printf("bytes left: %d\n", strlen(buffer)); memset(clients[j].line_buffer, 0, sizeof(clients[j].line_buffer)); strncpy(clients[j].line_buffer, buffer, strlen(buffer)); //printf("line buffer: %s", clients[j].line_buffer); } else { memset(clients[j].line_buffer, 0, sizeof(clients[j].line_buffer)); } } } } } } } } }