나는 채팅 서버와 클라이언트에서 겪고있는 문제에 대한 해결책을 생각하면서 최악의 상황에 직면하고 있습니다.C++ 멀티 클라이언트/서버 채팅
클라이언트는 사용자 이름을 묻고 답을 [Y/N]으로하여 사용자에게 연결을 요청합니다.
예를 들자면 클라이언트가 서버에 연결해야합니다. 클라이언트가 별도의 스레드 (여러 클라이언트를 처리하기 위해 필요합니다.하지만 내 문제는 하나 이상의 사용자가 가입 할 때 (현재 사용자의 사용자 이름 로그인하면 마지막으로 채팅에 참여한 사람으로 변경됩니다. 그 동안 (서버에 사용자 이름이 표시되고 클라이언트 화면에는 사라지고 이상한 징후가 나타나지 않거나 전혀 표시되지 않습니다.)
내가 필요한 것도 (사용자 자신을 제외하고) 연결된 다른 클라이언트에게 메시지를 배포하는 것입니다. (사용자 제외)
코드 서버 :
#include "stdafx.h"
long antwoord;
char chatname[100];
char bericht[498];
char sbericht[498];
using namespace std;
DWORD WINAPI SocketHandler(void*);
//our main function
void main()
{
//here we set the Winsock-DLL to start
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD(2,1);
//here the Winsock-DLL will be started with WSAStartup
//version of the DLL
antwoord = WSAStartup(DLLVERSION, &wsaData);
if(antwoord != 0)
{
WSACleanup();
exit(1);
}
else
{
cout << "WSA started successfully" <<endl;
cout << "The status: \n" << wsaData.szSystemStatus <<endl;
}
//the DLL is started
//structure of our socket is being created
SOCKADDR_IN addr;
//addr is our struct
int addrlen = sizeof(addr);
//socket sListen - will listen to incoming connections
SOCKET sListen;
//socket sConnect - will be operating if a connection is found.
SOCKET sConnect;
//setup of our sockets
//opgezocht op internet - AF_INET bekend dat het lid is van de internet familie
//Sock_STREAM betekenend dat onze socket een verbinding georiënteerde socket is.
sConnect = socket(AF_INET,SOCK_STREAM,NULL);
//now we have setup our struct
//inet_addr is our IP adres of our socket(it will be the localhost ip
//that will be 127.0.0.1
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//retype of the family
addr.sin_family = AF_INET;
//now the server has the ip(127.0.0.1)
//and the port number (4444)
addr.sin_port = htons(4444);
//here we will define the setup for the sListen-socket
sListen = socket(AF_INET,SOCK_STREAM,NULL);
if (sConnect == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
WSACleanup();
}
else
{
cout << "Connect socket() is OK!" <<endl;
}
if(sListen == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
WSACleanup();
}
else
{
cout << "Listen socket() is OK!" <<endl;
}
//here the sListen-socket will be bind
//we say that the socket has the IP adress of (127.0.0.1) and is on port (4444)
//we let the socket become the struct "addr"
if(bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
cout << "bind() failed: \n" << WSAGetLastError() <<endl;
WSACleanup();
exit(1);
}
else{
cout << "bind() is OK!" <<endl;
}
if(listen(sListen, 10) == -1){
cout << "Error listening %d\n" << WSAGetLastError() <<endl;
}
//here we will tell what the server must do when a connection is found
//therefor we will create an endless loop
cout << "Waiting for a incoming connection..." <<endl;
//now we let the socket listen for incoming connections
//SOMAXCOMM heeft het nut dat het dan voordurend luisterd naar inkomende verbindingen zonder limiet
int* csock;
while(true)
{
csock = (int*)malloc(sizeof(int));
//if a connection is found: show the message!
if((*csock = accept(sListen, (SOCKADDR*)&addr, &addrlen))!= INVALID_SOCKET)
{
cout << "A Connection was found with :" << inet_ntoa(addr.sin_addr) <<endl;
antwoord = send(*csock, "Welcome to our chat:", 21,NULL);
CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
cout << *csock <<endl;
}
}
}
//sbericht is the message
DWORD WINAPI SocketHandler(void* lp)
{
int *csock = (int*)lp;
for(;;)
{
antwoord = recv(*csock, sbericht, sizeof(sbericht), NULL);
antwoord = recv(*csock, chatname, sizeof(chatname), NULL);
while(antwoord = recv(*csock, sbericht, sizeof(sbericht), NULL) && (antwoord = recv(*csock, sbericht, sizeof(sbericht), NULL)))
{
printf("%s\: \"%s\"\n", chatname, sbericht);
antwoord = send(*csock, sbericht, sizeof(sbericht), NULL);
antwoord = send(*csock, chatname, sizeof(chatname), NULL);
}
return 0;
}
}
클라이언트 코드 :
나는 (난 그냥 소켓 프로그래밍 할 수 배우고)하지만이 일을 알아낼 수 없습니다 잘 작성하지 않은 경우#include "stdafx.h"
using namespace std;
//our main function
int main()
{
//here we set the Winsock-DLL to start
string bevestiging;
char chatname[100];
char bericht[250];
char sbericht[250];
string strbericht;
string strsbericht;
long antwoord;
//here the Winsock-DLL will be started with WSAStartup
//version of the DLL
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD(2,1);
antwoord = WSAStartup(DLLVERSION, &wsaData);
if(antwoord != 0)
{
exit(1);
}
else
{
cout << "WSA started successfully" <<endl;
cout << "The status: \n" << wsaData.szSystemStatus <<endl;
}
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
SOCKET sConnect;
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
if (sConnect == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
}
else
{
cout << "socket() is OK!\n" <<endl;
}
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(4444);
cout << "What is your chat name?" <<endl;
cin.getline(chatname, 100);
cout << "Do you want to connect to the server? [Y/N]" <<endl;
cin >> bevestiging;
if (bevestiging == "N")
{
exit(1);
}
else
{
if(bevestiging == "Y")
{
connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
antwoord = recv(sConnect, bericht, sizeof(bericht), NULL);
strbericht = bericht;
cout << strbericht << chatname <<endl;
while(true)
{
if(antwoord > 1)
{
cin.clear();
cin.sync();
cout << chatname << " :" <<endl;
cin.getline(sbericht, sizeof(sbericht));
antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = send(sConnect, chatname, sizeof(chatname), NULL);
while(antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL) && (antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL)))
{
antwoord = recv(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = recv(sConnect, chatname, sizeof(chatname), NULL);
cout << chatname << ":" <<endl;
cout << sbericht <<endl;
cin.getline(sbericht, 250);
}
}
else
{
cout << "The connection to the server has been lost... \n" << "please exit the client." <<endl;
}
}
죄송합니다. 그러니 나에게 열심히하지 말고, 나는 여전히 배울 필요가 있지만 필요한 것들을 찾을 수 없습니다. 그래서 누군가가 내게 그것을하는 방법을 보여줄 수 있다면, 나는 그것이 그 일과 그 이유를 볼 수 있다고 생각합니다.
항상 배웁니다. (저는 현재 beejee의 네트워크 프로그래밍 튜토리얼로도 바쁘다).
이 질문은 매우 광범위합니다. 사실 몇 가지 질문이 있습니다. 한 번에 한 가지만 물어보고 특정 질문을 다루는 최소한의 예에 제공된 코드를 자르십시오. 좋은 SO 질문에 대한 더 많은 힌트는 http://tinyurl.com/sohints에서 찾을 수 있습니다. –
나는이 프로젝트를 두 부분으로 나눌 것을 권한다 : '비 스레드 (non-threaded)'서버로 네트워킹 측면을 완전히 이해하고, stdio/iostream과 완전히 다른 '스레딩 샌드 박스'를 사용해야한다. 당신이 그들을 개별적으로 잘 이해하지 못한다면, 당신은 악몽을 꾼다. – kfmfe04
좋아, 이제이 문제에 이르렀다. [링크] (http://i42.tinypic.com/awq81h.jpg) –