#include #include #include #include #include #include #define PORT 8080 #define TCP_PACKET_SIZE 1024 // 1KB chunks for sending typedef struct SDLFramework { SDL_Window* window; SDL_Renderer* renderer; SDL_Texture* texture; } SDLFramework; int TCP_connect(int *fd) { int server_fd, client_fd; struct sockaddr_in server_addr, client_addr; socklen_t client_len = sizeof(client_addr); // Create socket server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("Can't create socket"); return -1; } // Allow port reuse int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // Setup server address memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); // Bind socket if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Can't bind"); close(server_fd); return -1; } // Listen for connections if (listen(server_fd, 1) < 0) { perror("Can't listen"); close(server_fd); return -1; } printf("Server listening on port %d...\n", PORT); client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd < 0) { perror("Can't accept"); close(server_fd); return -1; } printf("Connection accepted from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); fd[0] = server_fd; fd[1] = client_fd; return 0; } void TCP_disconnect(int *fd) { close(fd[0]); // server_fd close(fd[1]); // client_fd } void TCP_screen_info(int *fd, int *width, int *height, int *bpp, size_t *buffer_size) { recv(fd[1], width, sizeof(int), 0); recv(fd[1], height, sizeof(int), 0); recv(fd[1], bpp, sizeof(int), 0); *buffer_size = (*width) * (*height) * (*bpp / 8); printf("width = %d\n", *width); printf("height = %d\n", *height); printf("bpp = %d\n", *bpp); printf("buffer_size = %zu\n", *buffer_size); } unsigned char *TCP_receive_data(int client_fd, size_t buffer_size) { // Allocate the buffer with the size that the client communicated unsigned char *buffer = malloc(buffer_size); if (!buffer) { perror("malloc failed"); return NULL; } int total_received = 0; while (total_received < buffer_size) { // Calculate how many byte i still have to receive (could be TCP_PACKET_SIZE or less) int to_receive = 0; if (buffer_size - total_received > TCP_PACKET_SIZE) { to_receive= TCP_PACKET_SIZE; } else { to_receive = (buffer_size - total_received); } // Receive the package and update the total_sent value int received = recv(client_fd, buffer + total_received, to_receive, 0); total_received += received; } return buffer; } void initialize_SDL(SDLFramework *framework, int width, int height) { SDL_Init(SDL_INIT_VIDEO); framework->window = SDL_CreateWindow("Viewer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE); framework->renderer = SDL_CreateRenderer(framework->window, -1, SDL_RENDERER_ACCELERATED); framework->texture = SDL_CreateTexture(framework->renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height); return; } int main() { int fd[2]; // array containing server_fd as first element and client_fd as second unsigned char *buffer; int width; int height; int bpp; size_t buffer_size; SDLFramework framework; SDL_Event event; int windowWidth, windowHeight; // Connecting to the client and receiving the screen information TCP_connect(fd); TCP_screen_info(fd, &width, &height, &bpp, &buffer_size); initialize_SDL(&framework, width, height); int i=0; while(1){ // Receiving from the client the buffer buffer = TCP_receive_data(fd[1], buffer_size); printf("Buffer received[%d]\n", i); // Handle the event (if quit then TODO, if resize just aknowledge (the rendering will handle this)) while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { } if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { } } // Display the image SDL_UpdateTexture(framework.texture, NULL, buffer, width * 4); SDL_RenderClear(framework.renderer); SDL_GetWindowSize(framework.window, &windowWidth, &windowHeight); SDL_Rect destRect = {0, 0, windowWidth, windowHeight}; SDL_RenderCopy(framework.renderer, framework.texture, NULL, &destRect); SDL_RenderPresent(framework.renderer); i++; } // Cleaning SDL_DestroyTexture(framework.texture); SDL_DestroyRenderer(framework.renderer); SDL_DestroyWindow(framework.window); SDL_Quit(); TCP_disconnect(fd); return 0; }