Outils pour utilisateurs

Outils du site


lang:c:net:client_serveur

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
lang:c:net:client_serveur [2022/09/30 14:04] – Mise en forme pour send/recv rootlang:c:net:client_serveur [2023/01/27 15:35] (Version actuelle) – [connect sous Windows] : ajout d'une source root
Ligne 1: Ligne 1:
 =====TCP===== =====TCP=====
  
-====send/recv====+====connect sous Windows==== 
 + 
 +Pour ne pas avoir de connect bloquant et maitriser le timeout, on peut utiliser le code suivant : 
 + 
 +<code c> 
 +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"); 
 +
 +</code> 
 + 
 +[[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====
  
 <WRAP center round important 60%> <WRAP center round important 60%>
Ligne 186: Ligne 226:
 } }
 </file> </file>
 +
 +====sendmsg/recvmsg sous Linux====
 +
 +Transfert d'un file descripteur via socket Unix.
 +
 +<WRAP center round important 60%>
 +Il faut passer par un fichier temporaire. Je n'ai pas réussi à transposer le code par des ports TCP/IP.
 +</WRAP>
 +
 +
 +===Serveur===
 +
 +<code c>
 +#include <fcntl.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <sys/socket.h>
 +#include <sys/un.h>
 +#include <unistd.h>
 +
 +#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;
 +}
 +</code>
 +
 +
 +===Client===
 +
 +<code c>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <sys/socket.h>
 +#include <sys/un.h>
 +#include <unistd.h>
 +
 +#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;
 +}
 +</code>
  
 =====UDP===== =====UDP=====
lang/c/net/client_serveur.1664539468.txt.gz · Dernière modification : 2022/09/30 14:04 de root