Многопоточный сервер-клиент C

Здравствуйте, у меня проблема с потоками и реализацией клиента и сервера, я создал 2 клиента, которые записывают в сокет бесконечные числа. для управления двумя клиентами в sever.c я создаю потоки каждый раз, когда принимается новое соединение. он работает, но если запущен один клиент, он работает, но если я запустил второй, первый прервался; как я могу распечатать поочередно? я бы хотел: G1 G2 G1 и т. д.

G1.

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string.h>
#include <stdlib.h> 
#include <errno.h> 
#include <signal.h>
#include <time.h> 
void error(char *msg)
{
    perror(msg);
    exit(0);
}
struct message {  //dichiarazione struct
 time_t timestamp;  
 char g;  //process identifier
 int x;
};
int main(int argc, char *argv[])
{
  int sockfd, portno, n,i;
  struct message m1;
  struct sockaddr_in serv_addr;
  struct hostent *server;
  struct timespec delay;
  delay.tv_sec = 1;
  delay.tv_nsec = 0; //in microseconds
  long int offset=1000000;
  struct timeval tv;
  char buffer[256];
  if (argc < 3) {
    fprintf(stderr,"usage %s hostname port\n", argv[0]);
    exit(0);
  }
  portno = atoi(argv[2]);
  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
  if (sockfd < 0) 
    error("ERROR opening socket");
  server = gethostbyname(argv[1]);
  if (server == NULL) {
    fprintf(stderr,"ERROR, no such host\n");
    exit(0);
  }
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_UNIX;
  bcopy((char *)server->h_addr, 
  (char *)&serv_addr.sin_addr.s_addr,
  server->h_length);
  serv_addr.sin_port = htons(portno);

  if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting");
    while(1){
    m1.timestamp=time(NULL);
    m1.x=i;
    m1.g=getpid();

    n = write(sockfd,&m1,sizeof(m1));
    if (n < 0) 
      error("ERROR writing to socket");
    i++;
    delay.tv_nsec=offset+rand()%offset;
    nanosleep(&delay,NULL);
  }

  return 0;
}`

R.c (сервер)

#include<stdio.h>

#include<stdlib.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<string.h>

#include <arpa/inet.h>

#include <fcntl.h> // for open

#include <unistd.h> // for close

#include<pthread.h>
struct message {  //dichiarazione struct
  time_t timestamp;  
  char g;  //process identifier
  int x;
};
struct message client_message;

char buffer[1024];

static void * socketThread(void *arg)
{ 
  while(1) {
    int newSocket = *((int *)arg);

    recv(newSocket , &client_message , sizeof(client_message), 0);

    printf("message %d  %d %ld\n",client_message.x,client_message.g,client_message.timestamp);
    fflush(stdout);
    sleep(1);
  }
}

int main(){

  int serverSocket, newSocket;

  struct sockaddr_in serverAddr;

  struct sockaddr_storage serverStorage;

  socklen_t addr_size;

  //Create the socket. 

  serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);

  // Configure settings of the server address struct

  // Address family = Internet 

  serverAddr.sin_family = AF_UNIX;

  //Set port number, using htons function to use proper byte order 

  serverAddr.sin_port = htons(6005);

  //Set IP address to localhost 

  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

  //Set all bits of the padding field to 0 

  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

  //Bind the address struct to the socket 

  bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

  //Listen on the socket, with 40 max connection requests queued 

  if (listen(serverSocket,50)!=0)
  {
    printf("Error\n");
    return -1;
  }
  printf("Listening\n");

  pthread_t tid[60];

  int i = 0;

  while(1)
  {
        //Accept call creates a new socket for the incoming connection

        addr_size = sizeof serverStorage;

        newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);

        //for each client request creates a thread and assign the client request to it to process

        //so the main thread can entertain next request

        if ( pthread_create(&tid[i], NULL, socketThread, &newSocket) != 0 )
           printf("Failed to create thread\n");
        else
          ++i;
  }

  return 0;
}

Спасибо !

Вы передаете сокет как указатель. Затем в while вы перечитываете этот указатель, поэтому, когда подключается второй сокет, первый сокет теперь использует второй. Решение: не передавайте указатель на поток. Или переместите int newSocket = *((int *)arg); перед петлей while.

Johnny Mopp 16.12.2018 16:18

@JohnnyMopp Спасибо! Идеальный ответ, теперь он работает. Спасибо-спасибо

Jordan.M 16.12.2018 16:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
81
1

Ответы 1

Как я понимаю, в серверном коде в функции потока socketThread () вы получаете значение дескриптора сокета на каждой итерации. Но когда вы принимаете новое соединение, в этот адрес записывается новое значение дескриптора нового сокета. И после этого каждый поток получает данные только из последнего сокета.

Вы должны передать дескриптор сокета socketThread () по значению (а не по указателю)!

Другие вопросы по теме