=====TCP===== ====connect sous Windows==== Pour ne pas avoir de connect bloquant et maitriser le timeout, on peut utiliser le code suivant : int error = -1; int len = sizeof(int); timeval tm; fd_set set; unsigned long ul = 1; ioctlsocket(Socket, FIONBIO, &ul); // set as non-blocking bool ret = false; if (connect(Socket, (struct sockaddr *)&ServerAddress, sizeof(ServerAddress)) == -1) { tm.tv_sec = 10; // set the timeout. 10s tm.tv_usec = 0; FD_ZERO(&set); FD_SET(Socket, &set); if (select(Socket + 1, NULL, &set, NULL, &tm) > 0) { getsockopt(Socket, SOL_SOCKET, SO_ERROR, (char *)&error, /*(socklen_t *)*/ &len); if (error == 0) ret = true; else ret = false; } else ret = false; } else ret = true; ul = 0; ioctlsocket(Socket, FIONBIO, &ul); // set as blocking if (!ret) { closesocket(Socket); fprintf(stderr, "Cannot Connect the server!/n"); } [[https://social.msdn.microsoft.com/Forums/en-US/2202d113-212d-420d-9e7b-11268de9ce90/win32-tcp-connect-timeout|Win32: TCP connect timeout]] {{ :lang:c:net:win32_tcp_connect_timeout_27_01_2023_15_32_49_.html |Archive du 24/08/2018 le 27/01/2023}} ====send/recv sous Linux==== TODO. recv en non bloquant. {{:lang:c:net:tcp_ip_socket_diagram.png|Diagramme de séquence TCP}} [[https://www.bogotobogo.com/cplusplus/sockets_server_client.php|SOCKETS - SERVER & CLIENT - 2020]] {{ :lang:c:net:c_tutorial_sockets_-_server_client_-_2020_2020-04-26_10_45_46_pm_.html |Archive du 2020 le 26/04/2020}} [[https://www.bogotobogo.com/cplusplus/sockets_server_client_2.php|SOCKETS - SERVER & CLIENT 2 - 2020]] {{ :lang:c:net:c_tutorial_sockets_-_server_client_2_-_2020_2020-04-26_10_53_42_pm_.html |Archive du 2020 le 26/04/2020}} [[https://www.bogotobogo.com/cplusplus/sockets_server_client_3.php|SOCKETS - SERVER & CLIENT 3 - 2020]] {{ :lang:c:net:c_tutorial_sockets_-_server_client_3_-_2020_2020-04-26_10_55_01_pm_.html |Archive du 2020 le 26/04/2020}} [[https://www.binarytides.com/server-client-example-c-sockets-linux/|Server and client example with C sockets on Linux]] {{ :lang:c:net:server_and_client_example_with_c_sockets_on_linux_binarytides_2020-04-26_10_47_54_pm_.html |Archive du 27/11/2012 le 26/04/2020}} [[http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/|Programming UNIX Sockets in C - Frequently Asked Questions]] {{ lang:c:net:unix-socket-faq.zip |Archive FAQ}} {{ lang:c:net:examples.tar.gz |Archive Source}} [[https://vincent.bernat.ch/fr/blog/2014-tcp-time-wait-state-linux|TCP TIME-WAIT & les serveurs Linux à fort trafic]] {{ :lang:c:net:tcp_time-wait_les_serveurs_linux_a_fort_trafic_⁕_vincent_bernat_2020-04-26_10_49_25_pm_.html |Archive du 24/02/2014 le 26/04/2020}} ===Serveur=== #define _GNU_SOURCE #include #include #include #include #include #include #include // the thread function void *connection_handler(void *socket_desc); int main(int argc, char *argv[]) { int socket_desc, client_sock, c, *new_sock; struct sockaddr_in server, client; // Create socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Could not create socket"); } puts("Socket created"); // Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(8888); // Bind if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { // print the error message perror("bind failed. Error"); return 1; } puts("bind done"); // Listen listen(socket_desc, 3); // Accept and incoming connection puts("Waiting for incoming connections..."); c = sizeof(struct sockaddr_in); while ((client_sock = accept4(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c, 0))) { puts("Connection accepted"); pthread_t sniffer_thread; new_sock = (int *)malloc(sizeof(int)); *new_sock = client_sock; if (pthread_create(&sniffer_thread, NULL, connection_handler, (void *)new_sock) < 0) { perror("could not create thread"); return 1; } // Now join the thread , so that we dont terminate before the thread // pthread_join( sniffer_thread , NULL); puts("Handler assigned"); } if (client_sock < 0) { perror("accept failed"); return 1; } return 0; } /* * This will handle connection for each client * */ void *connection_handler(void *socket_desc) { // Get the socket descriptor int sock = *(int *)socket_desc; int read_size; char *message, client_message[2000]; // Send some messages to the client message = "Greetings! I am your connection handler\n"; write(sock, message, strlen(message) + 1); message = "Now type something and i shall repeat what you type \n"; write(sock, message, strlen(message) + 1); // Receive a message from client while ((read_size = recv(sock, client_message, 2000, 0)) > 0) { // Send the message back to client write(sock, client_message, strlen(client_message) + 1); } if (read_size == 0) { puts("Client disconnected"); fflush(stdout); } else if (read_size == -1) { perror("recv failed"); } // Free the socket pointer free(socket_desc); return 0; } ===Client=== #include #include #include #include #include #include int main(int argc, char *argv[]) { int sock; struct sockaddr_in server; char message[1000], server_reply[2000]; // Create socket sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("Could not create socket"); } puts("Socket created"); server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons(8888); // Connect to remote server if (connect(sock, (struct sockaddr *)(&server), sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } puts("Connected\n"); // keep communicating with server while (1) { printf("Enter message : "); scanf("%s", message); // Send some data if (send(sock, message, strlen(message) + 1, 0) < 0) { puts("Send failed"); return 1; } // Receive a reply from the server if (recv(sock, server_reply, 2000, 0) < 0) { puts("recv failed"); break; } puts("Server reply :"); puts(server_reply); } close(sock); return 0; } ====sendmsg/recvmsg sous Linux==== Transfert d'un file descripteur via socket Unix. Il faut passer par un fichier temporaire. Je n'ai pas réussi à transposer le code par des ports TCP/IP. ===Serveur=== #include #include #include #include #include #include #include #define SOCK_PATH "/tmp/usocket" int send_msg_to_client(int socketfd, int fd) { struct msghdr msg; struct iovec iov; int s; char buf[CMSG_SPACE(sizeof(fd))]; memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = ""; iov.iov_len = 1; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); msg.msg_flags = 0; struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); memmove(CMSG_DATA(cmsg), &fd, sizeof(fd)); msg.msg_controllen = CMSG_SPACE(sizeof(fd)); s = sendmsg(socketfd, &msg, 0); if (s < 0) { perror("sendmsg"); return 0; } return s; } int main(int argc, char *argv[]) { int s, s2, len, slen; socklen_t t; struct sockaddr_un local, remote; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_PATH); unlink(local.sun_path); len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(s, (struct sockaddr *)&local, len) == -1) { perror("bind"); exit(1); } if (listen(s, 5) == -1) { perror("listen"); exit(1); } printf("Waiting for a connection...\n"); t = sizeof(remote); if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) { perror("accept"); exit(1); } printf("Connected.\n"); int fd = open("./z7.c", O_RDONLY); if (fd < 0) printf("Parent Failed to open file %s for reading\n", "./z7.c"); slen = send_msg_to_client(s2, fd); if (slen < 0) perror("send"); printf("sent data length: %d\n", slen); close(s2); return 0; } ===Client=== #include #include #include #include #include #include #define SOCK_PATH "/tmp/usocket" int recv_msg_from_server(int socketfd) { struct msghdr msg = {0}; /* On Mac OS X, the struct iovec is needed, even if it points to minimal data */ char m_buffer[1]; struct iovec io = {.iov_base = m_buffer, .iov_len = sizeof(m_buffer)}; msg.msg_iov = &io; msg.msg_iovlen = 1; char c_buffer[256]; msg.msg_control = c_buffer; msg.msg_controllen = sizeof(c_buffer); if (recvmsg(socketfd, &msg, 0) < 0) printf("Child Failed to receive message\n"); struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); printf("Child About to extract fd\n"); int fd; memmove(&fd, CMSG_DATA(cmsg), sizeof(fd)); printf("Child Extracted fd %d\n", fd); return fd; } int main(void) { int s, len, slen; struct sockaddr_un remote; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } printf("Trying to connect...\n"); remote.sun_family = AF_UNIX; strcpy(remote.sun_path, SOCK_PATH); len = strlen(remote.sun_path) + sizeof(remote.sun_family); if (connect(s, (struct sockaddr *)&remote, len) == -1) { perror("connect"); exit(1); } printf("Connected.\n"); slen = recv_msg_from_server(s); char buffer[256]; int nbytes; if ((nbytes = read(slen, buffer, sizeof(buffer))) > 0) { printf("Child read: [[%.*s]]\n", nbytes, buffer); } close(s); return 0; } =====UDP===== TODO