RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-554242

kuskas112's questions

Martin Hope
kuskas112
Asked: 2023-11-13 18:38:06 +0000 UTC

Windows 错误严重性代码之间有什么区别

  • 5

有关 Windows 中错误严重性代码有何不同的问题。我知道错误代码中的最高 2 位负责错误严重性代码。二进制形式:00 - 成功,01 - 信息,10 - 警告,11 - 错误。这些代码之间有什么区别,每个代码的生成必须发生什么?我很乐意阅读文献或文章链接,否则我无法在任何地方找到有关此的信息。

c++
  • 1 个回答
  • 34 Views
Martin Hope
kuskas112
Asked: 2023-05-13 04:44:16 +0000 UTC

如何用 C 语言组织客户端-服务器应用程序的服务器线程的工作?

  • 8

挑战是编写一个简单的网络聊天。语言没有根本区别,但我决定用 C 编写。服务器必须能够同时处理多个用户,而用户又必须能够请求所有活动用户的列表并向他们写入消息。如果用户退出网络,他/她将相应地与服务器断开连接并从活动用户列表中删除。

当我添加注册和发布活跃用户列表的功能时,我遇到了一个问题,在新创建的线程中访问服务器不会出现问题,但是如果您从以前创建的线程访问,服务器会卡住。
我认为重点是同时使用内存,尽管这不太可能,因为我是从一台机器上单独输入所有内容的,但为了以防万一我添加了互斥体,它没有帮助。

我还认为它可能是输入缓冲区堵塞,但在某些地方清除它的功能要么什么都不做,要么只会让情况变得更糟。
我最后的猜测是我的实现根本不适合 pthread 线程,我需要使用共享内存和 fork() 重写所有内容,但我想避免这种情况。

这是服务器代码
:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>

#define PORT 8080
#define BUFFER_SIZE 1024
#define MAX_CONNECTIONS 5
#define REGISTRATION '1'
#define CHECKINFO '2'
#define SENDMESSAGE '3'
#define EXIT '4'

struct Node {
    char name[30];
    struct Node* next;
};

struct Node* createNode(char* name) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    for(int i = 0; i < 30; i++)
    {
      newNode->name[i] = name[i];
    }
    newNode->next = NULL;
    return newNode;
}

void CleanStdin()
{
  char c;
  while ((c = getchar()) != '\n' && c != EOF) {}
}


void pushBack(struct Node** headRef, char* name) {
    struct Node* newNode = createNode(name);
    if (*headRef == NULL) {
        *headRef = newNode;
        return;
    }
    struct Node* temp = *headRef;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = newNode;
}

void Delete(struct Node** headRef, char* name)
{
  struct Node* temp = *headRef;
  struct Node* prev = temp;
  if (strcmp(temp->name, name) == 0) 
  {
    *headRef = NULL;
    return;
  }
  while (temp != NULL) 
  {
    if (strcmp(temp->name, name) == 0) 
    {
        prev->next = temp->next;
        free(temp);
        return;
    }
    prev = temp;
    temp = temp->next;
  }
}

int Find(struct Node** headRef, char* name)
{
  struct Node* temp = *headRef;
  while (temp != NULL) 
  {
    if (strcmp(temp->name, name) == 0) 
    {
        return 1;
    }
    temp = temp->next;
  }
  return 0;
}

void PrintUsers(struct Node** headRef, int sock, int usersVal)
{
  struct Node* temp = *headRef;
  for (int i = 0; i < usersVal; i++) 
  {
    send(sock, temp->name, 30, 0);
    temp = temp->next;
  }
}


  pthread_t thread_id;
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  struct Node* head = NULL;
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE];
    int usersVal = 0;

void* mainFunc()
{
  char name[30];
  // Чтение сообщения от клиента
    while(1)
    {
      //CleanStdin();
      memset(buffer, (char)0, BUFFER_SIZE);
    char operation;
    
    if ( operation == REGISTRATION)
    {
      read(new_socket, name, 30);
      int RegCode;
      if (Find(&head, name) == 1)
      {
        printf("User already registered: %s", name);
        RegCode = 1;
      }
      else
      {
        printf("User successfully registered: %s", name);
        pushBack(&head, name);
        pthread_mutex_lock(&mutex);
        usersVal++;
        pthread_mutex_unlock(&mutex);
        RegCode = 0;
      }
      send(new_socket, &RegCode, 4, 0);
    }
    else if (operation == CHECKINFO) 
    {
      pthread_mutex_lock(&mutex);
      printf("\nUserval = %d\n", usersVal);
      send(new_socket, &usersVal, 4, 0);
      pthread_mutex_unlock(&mutex);
      //PrintUsers(&head, new_socket, usersVal);
    }
    else if (operation == EXIT)
    {
      close(new_socket);
      printf("\nExited!\n");
      //Delete(&head, name);
      pthread_mutex_lock(&mutex);
      usersVal--;
      pthread_mutex_unlock(&mutex);
      CleanStdin();
      break;
    }
    read(new_socket, &operation, 1);
  }
  return NULL;
}

int main(int argc, char const *argv[]) {
  
    // Создание сокета
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
      
    // Присваивание опции сокету (можно повторно использовать адрес)
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons( PORT );
      
    // Привязка сокета к адресу и порту
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

// Ожидание входящих соединений
    if (listen(server_fd, MAX_CONNECTIONS) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    // Принятие входящего соединения
    while(1)
    {
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) 
    {
        perror("accept");
        exit(EXIT_FAILURE);
    }
    
    printf("\nConnected!\n");
    pthread_create(&thread_id, NULL, mainFunc, NULL);
  }
    return 0;

}

客户:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024
#define REGISTRATION '1'
#define CHECKINFO '2'
#define SENDMESSAGE '3'
#define EXIT '4'

int Socket(int domain, int type, int protocol)
{
  int sock = socket(domain, type, protocol);
  if (sock < 0) {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }
    return sock;
}

void Inet_pton(int af, const char *src, void *dst)
{
  if (inet_pton(af, src, dst) <= 0) {
        perror("Invalid server address");
        exit(EXIT_FAILURE);
    }
    
}

void Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
  if (connect(sockfd, addr, addrlen) < 0) {
        perror("Failed to connect to server");
        exit(EXIT_FAILURE);
    }
}

void Send(int sockfd, const void *buf, size_t len, int flags)
{
  if (send(sockfd, buf, len, flags) < 0) 
    {
      perror("Failed to send message to server");
      exit(EXIT_FAILURE);
    }
}

void Recv(int sockfd, void *buf, size_t len, int flags)
{
  if (recv(sockfd, buf, len, flags) < 0) {
        perror("Failed to receive message from server");
        exit(EXIT_FAILURE);
    }
}

// Создание сокета и подключение к серверу
int Conn()
{
  int sock = Socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(SERVER_PORT);
    Inet_pton(AF_INET, SERVER_ADDRESS, &server_address.sin_addr);
    Connect(sock, (struct sockaddr*) &server_address, sizeof(server_address));
    
    return sock;
}

void CleanStdin()
{
  char c;
  while ((c = getchar()) != '\n' && c != EOF) {}
}

int main() {
  char buffer[BUFFER_SIZE];
    char symb, operation;
    int sock = Conn();
    // Первоначальная регистрация
    operation = REGISTRATION;
  Send(sock, &operation, 1, 0);
  printf("\nEnter Name: ");
  fgets(buffer, 30, stdin);
  Send(sock, buffer, 30, 0);
  int RegCode;
  Recv(sock, &RegCode, 4, 0);
  if (RegCode == 1)
  {
    printf("You was registered before");
  }
  else if (RegCode == 0)
  {
    printf("You were successfully registered");
  }
    while(1)
    {
    CleanStdin();
    memset(buffer, (char)0, BUFFER_SIZE);
    printf("\n1. Get users info");
    printf("\n3. Exit\n");
    symb = getchar();
    switch (symb)
    {
    // Регистрация пользователя
      case '1':
      {
        operation = CHECKINFO;
        Send(sock, &operation, 1, 0);
        int usersVal;
        Recv(sock, &usersVal, 4, 0);
        printf("\nAmount of users = %d\n", usersVal);
        /*for(int i = 0; i < usersVal; i++)
        {
          char name[30];
          Recv(sock, name, 30, 0);
          printf("\nUser: %s\n", name);
        }*/
        break;
      }
      case '3':
      {
        operation = EXIT;
        printf("Exiting...\n");
        Send(sock, &operation, 1, 0);
        exit(0);
      }
      
    }
  }
    
    return 0;
}

不严格判断,我自己知道这一切的样子,我写了一天不停,尽我所能集体耕种,只是为了完成。

我评论了我认为可能包含错误的行,但没有区别。如果您按顺序执行以下操作,则会发生错误:

  1. 启动服务器
  2. 在另一个终端窗口中运行客户端应用程序(我正在运行 Ubuntu)
  3. 输入名字
  4. 在第三个终端窗口中启动一个新的客户端应用程序而不关闭旧的
  5. 输入名称并退出
  6. 转到第二个窗口并尝试获取活跃用户列表(现在有一个存根只显示活跃用户的数量)

是否可以修复此问题,或重做已经存在的内容以使其正常工作?如果有任何建议,我将不胜感激。下面是对该问题的更详细描述。

有必要实施 - “CHAT”。

Необходимо реализовать с использованием сетевых сокетов две программы: Клиент и Сервер. Сервер должен быть один. Клиентов может быть много.

Сервер.

После запуска работает в бесконечном цикле слушая закрепленный за ним сокет, пока не поступит команда на его завершения.

К серверу через сокет, могут поступать следующие виды запросов от клиента:

  1. Запрос на регистрацию (сервер должен вести список зарегистрированных клиентов). При поступлении данного запроса проверяется данный список, если клиент там не зарегистрирован, то происходит его регистрация. Клиенту отправляется ответ с подтверждением регистрации или сообщением о том, что он уже зарегистрирован.

  2. Запрос на получение списка зарегистрированных клиентов. В ответ сервер отправляет Имена клиентов, зарегистрированных в данный момент.

  3. Запрос на передачу сообщения клиенту. (в запросе указывается имя клиента получателя и текст сообщения). Если клиент получатель не зарегистрирован в чате, то отправителю сообщения отправляется об этом информация, иначе сообщение пересылается клиенту получателю.

  4. Запрос на отключение от чата. В этом случае клиент удаляется из чата.

Клиент.

После запуска запрашивает параметры сервера (адрес и порт), а также имя клиента и пытается подключиться к серверу – отправляет запрос на регистрацию. Если подключение невозможно (не получен ответ), то завершает свою работу.

Иначе либо ждет команду от пользователя, либо сообщение от сервера.

При поступлении сообщения, выводит имя отправителя и сам текст сообщения.

Пользователь может ввести следующие команды:

Получить список зарегистрированных в чате. В этом случае клиент запрашивает этот список на сервере и выводит его на экране.

Отправить сообщение. Указывается имя клиента получателя и текст сообщения.

Команда на завершение работы. Отправляется соответствующий запрос на сервер и программа завершает свою работу.

При выполнении лабораторной работы обязательно необходимо для взаимодействия использовать сокеты операционной системы.

c
  • 1 个回答
  • 39 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5