@offklid

Как прекратить отправку сообщений с одного клиента другому / сокеты С++?

Написал убогую программу чата на сокетах в С++. Отправка сообщений есть и работает, но когда выхожу из 1 клиента , на оставшихся бесконечно выводиться его последнее сообщение. Что делать? Я так думаю , что у меня не корректно закрыты сокеты , прошу помочь с этой проблемой.
Сервер
#include "stdafx.h" // ускорение компиляции . 
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <iostream>

#pragma warning(disable: 4996)//убирает ошибку устаревших библеотек

SOCKET Connections[100];// массив сокетов подключения
int Counter = 0; // индекс соединения
void ClientHandler(int index) {
	char msg[256];
	
	while (true) {
		recv(Connections[index], msg, sizeof(msg), NULL);
		for (int i = 0; i < Counter; i++) {
			send(Connections[i], msg, sizeof(msg), NULL);
		}
	}
}

int main(int argc, char* argv[]) {
	setlocale(0, "Rus");
	system("chcp 1251");
	//WSAStartup < Инициализация библиотеки <winsock2.h> для работы с сокетами
	WSAData wsaData;
	WORD DLLVersion = MAKEWORD(2, 1);
	if (WSAStartup(DLLVersion, &wsaData) != 0) {
		std::cout << "Error" << std::endl;
		exit(1);
	}
	SOCKADDR_IN addr; // структура адреса 
	int sizeofaddr = sizeof(addr);// размер адреса
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");// подлючение к 1 сети
	addr.sin_port = htons(1111);//(сетевой порядок) преобразует узловой порядок расположения байтов в сетевой порядок
	addr.sin_family = AF_INET; // подключение через итернет 

	SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);//создание сокета(слушать) для соединения 
	bind(sListen, (SOCKADDR*)&addr, sizeof(addr));//  Связывает сокет с конкретным адресом
	listen(sListen, SOMAXCONN);

	SOCKET newConnection;
	for (int i = 0; i < 100; i++) {
		newConnection = accept(sListen, (SOCKADDR*)&addr, &sizeofaddr);// создание сокета для работы(только на сервере)

		if (newConnection == 0) {
			std::cout << "Error #2\n";
		}
		else {
			char name_client[256];
			recv(newConnection, name_client, sizeof(name_client), NULL);// считывает с сокета 
			std::cout << "Клиент " << name_client << " Подключился!\n";
			Connections[i] = newConnection; // записываем соединение в массив
			Counter++; // следующие соединение
			CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandler, (LPVOID)(i), NULL, NULL);
		}
	}
	shutdown(sListen, 0);
	shutdown(newConnection, 0);
	closesocket(newConnection);
	closesocket(sListen);
	delete[100] Connections;
	system("pause");
	return 0;
}

Клиент
#include "stdafx.h"
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <iostream>

#pragma warning(disable: 4996)//убирает ошибку устаревших библеотек  

SOCKET Connection;// массив сокетов подключения

void ClientHandler() {
	char msg[256];
	while (true) {
		recv(Connection, msg, sizeof(msg), NULL);
		std::cout  << msg << std::endl;
	}
}

int main(int argc, char* argv[]) {
	//WSAStartup < Инициализация библиотеки <winsock2.h> для работы с сокетами
	WSAData wsaData;
	WORD DLLVersion = MAKEWORD(2, 1);
	if (WSAStartup(DLLVersion, &wsaData) != 0) {
		std::cout << "Error" << std::endl;
		exit(1);
	}

	SOCKADDR_IN addr; // структура адреса 
	int sizeofaddr = sizeof(addr);// размер адреса
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");// подлючение к 1 сети 
	addr.sin_port = htons(1111);// (сетевой порядок) преобразует узловой порядок расположения байтов в сетевой порядок
	addr.sin_family = AF_INET; // подключение через итернет 

	Connection = socket(AF_INET, SOCK_STREAM, NULL);
	if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) != 0) {
		std::cout << "Error: failed connect to server.\n";
		return 1;
	}
	std::cout << "Conected !\n";
	char name_client[256];
	std::cout << "Enter your online name\n";
	std::cin.getline(name_client, 256);
	send(Connection, name_client, sizeof(name_client), NULL);// записывает в сокет

	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandler, NULL, NULL, NULL);

	char msg1[256];
	while (true) {
		
		std::cin.getline(msg1, sizeof(msg1));
		//strcat(name_client, msg1);
		send(Connection, msg1, sizeof(msg1), NULL);
	}
	shutdown(Connection, 0);
	closesocket(Connection);
	system("pause");
	return 0;
}
  • Вопрос задан
  • 60 просмотров
Пригласить эксперта
Ответы на вопрос 1
Gremlin92
@Gremlin92
Целеустремленный
У тебя в серверной части перебираются все клиенты независимо, закрыли ли они соединение или нет, надо добавить массив булевский значений isAvailable[100] где истина если клиент сидит на соединений и ложь если уже отключился
SOCKET Connections[100];// массив сокетов подключения
int Counter = 0; // индекс соединения
void ClientHandler(int index) {
  char msg[256];
  while (true) {
    recv(Connections[index], msg, sizeof(msg), NULL);
    for (int i = 0; i < Counter; i++) {
      send(Connections[i], msg, sizeof(msg), NULL);
    }
  }
}

То есть что то такое
SOCKET Connections[100];// массив сокетов подключения
int Counter = 0; // индекс соединения
void ClientHandler(int index) {
  char msg[256];
  while (true) {
if(!isAvailable[index])
countinue;
    recv(Connections[index], msg, sizeof(msg), NULL);
    for (int i = 0; i < Counter; i++) {
      send(Connections[i], msg, sizeof(msg), NULL);
    }
  }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы