2014-03-01 3 views
1

3 개의 응용 프로그램, 하나의 서버, 2 개의 클라이언트가 있습니다. 나는 나의 클라이언트로부터 서버로 요청의 로그를 보내고 다른 클라이언트에 대한 정보를 보도록 요청할 수 있도록 이것을 프로그램하려고한다.하나의 서버에서 여러 개의 클라이언트 패킷 수신

질문 : 모든 3 개의 응용 프로그램 (모든 3 개의 Visual Studio 응용 프로그램에서 내 컴퓨터에서 수행)에 대해 동일한 IP 및 포트 번호를 사용하고 있습니다. 그렇지 않으면 서버에 연결하지 않을 것입니다. 이거 괜찮아?

서버에서 while 루프 외부에서 수신 대기 및 수신을 시도하면 다른 클라이언트에서는 작동하지 않지만 다른 클라이언트에서는 작동하지 않습니다. 내가 청취하려고 시도하고 while 루프 내에서 받아 들일 때 두 클라이언트 모두에서 작동하지만 하나 이상의 응답에 응답하지 않습니다. 내 문제는 무엇입니까? (모두 동일)

서버

struct Users { 

int message; 
char userName[50]; 
char ipAddress[50]; 
int PortNumber; 
bool online; 

}; 

int main() { 

//Create users 
Users client[2]; 

client[0].PortNumber = 20000; 
client[0].online = false; 
sprintf(&client[0].userName[0], "Albert"); 
sprintf(&client[0].ipAddress[0], "127.0.0.1"); 

client[1].PortNumber = 20000; 
client[1].online = false; 
sprintf(&client[1].userName[0], "Monique"); 
sprintf(&client[1].ipAddress[0], "127.0.0.1"); 


//Set up all the connection stuff 
struct sockaddr_in SvrAddr; 
SOCKET WelcomeSocket, ConnectionSocket; 
int PortNumber = 20000; 
int result; 
char IPAddress[] = "127.0.0.1"; 
char RxBuffer[128]; 
char TxBuffer[128]; 


WORD wVersionRequested; 
WSADATA wsaData; 

wVersionRequested = MAKEWORD(2,2); //For Server 


if(WSAStartup(wVersionRequested, &wsaData) != 0) 
    return -1; 


//Setting up the welcome socket 
WelcomeSocket = socket(AF_INET, SOCK_STREAM, 0); 

//Setting up the sockaddr svraddr structure 
SvrAddr.sin_family = AF_INET; 
SvrAddr.sin_addr.s_addr = inet_addr(IPAddress); 
SvrAddr.sin_port = htons(PortNumber); 


//Bind 
bind(WelcomeSocket, (sockaddr*)&SvrAddr, sizeof(SvrAddr)); 

//listening 
//listen(WelcomeSocket, 5); 

//temp users 
Users temp; 
//ConnectionSocket = accept(WelcomeSocket, NULL, NULL); 
ConnectionSocket = SOCKET_ERROR; 

//while loop for the connection 
while (1) { 

    listen(WelcomeSocket, 5); 

    if ((ConnectionSocket = accept(WelcomeSocket, NULL, NULL)) == SOCKET_ERROR) 
    { 
     return -1; 
    } 

    else { 

    int n = recv(ConnectionSocket, RxBuffer, sizeof(RxBuffer), 0); 

    if (n == 0) 
     break; 


    memcpy(&temp, RxBuffer, sizeof(struct Users)); 

    //cout << temp.message << temp.userName << endl << endl; 

    //check which message type is being sent 
    switch(temp.message) { 

    //if message type 1 
    case 1 : 
     for (int i = 0; i < 2; i++) { 

      //if receieved username matches with any username in the database 
      if (strcmp(temp.userName, client[i].userName) == 0) { 

       //assign the recieved users information to the matched one in database 
       strcpy(client[i].userName, temp.userName); 
       client[i].online = true; 
       client[i].message = 2; 

       cout << "Username: " << client[i].userName << endl << "Online status: " << client[i].online << endl << endl; 

       //send the acknowledgement packet 
       send(ConnectionSocket, (char *)&client[i], sizeof(struct Users), 0); 
       //closesocket(ConnectionSocket); 
      } 

     } 
     break; 

    //if message type 3 
    case 3 : 

     cout << "User being searched for: " << temp.userName << endl << endl; 
     for (int i = 0; i < 2; i++) { 

      //if receieved username matches with any username in the database 
      if (strcmp(temp.userName, client[i].userName) == 0) { 
       client[i].message = 4; 
       //send the acknowledgement packet 
       send(ConnectionSocket, (char *)&client[i], sizeof(struct Users), 0); 
       //closesocket(ConnectionSocket); 
      } 

     } 
     break; 

    default : 
     break; 

    } 

} 

} 

closesocket(ConnectionSocket); 
WSACleanup(); 
} 

클라이언트

struct Users { 

int message; 
char userName[50]; 
char ipAddress[50]; 
int PortNumber; 
bool online; 

}; 


int main() { 

struct sockaddr_in SvrAddr; 
SOCKET ClientSocket; 
int PortNumber = 20000; 
char IPAddress[] = "127.0.0.1"; 
//char message[] = "Hello this is the client."; 
char RxBuffer[128]; 

WORD wVersionRequested; 
WSADATA wsaData; 

wVersionRequested = MAKEWORD(2,3); //For Client 

if(WSAStartup(wVersionRequested, &wsaData) != 0) 
    return -1; 


ClientSocket = socket(AF_INET, SOCK_STREAM, 0); 

SvrAddr.sin_family = AF_INET; 
SvrAddr.sin_addr.s_addr = inet_addr(IPAddress); 
SvrAddr.sin_port = htons(PortNumber); 

connect(ClientSocket, (sockaddr*)&SvrAddr, sizeof(SvrAddr)); 



//cout << "Name: "; 
//cin >> login; 

//Send request to login 
int log; 
char * name = new char[128]; 
char * request = new char[128]; 
Users client; 
Users talkto; 


do { 

    cout << "To login press (1) to end press (2). "; 
    cin >> log; 
    flushall(); 

    if (log == 1) { 

     cout << "Username : "; 
     cin.getline(name, 128, '\n'); 
     cout << endl; 
     flushall(); 

     //Set client login info 
     strcpy(client.userName, name); 
     client.message = 1; 



     send(ClientSocket, (char *)&client, sizeof(struct Users), 0); 


     //Recieve acknowledgement 
     recv(ClientSocket, RxBuffer, sizeof(RxBuffer), 0); 
     //create temp users 
     Users temp; 

     memcpy(&temp, RxBuffer, sizeof(struct Users)); 

     //If logged in and received a message of type 2 (acknowledgement) 
     if (temp.message == 2) { 

      cout << "You have logged in." << endl << endl; 

      cout << "Enter user to request user information: "; 
      cin.getline(talkto.userName, 128, '\n'); 
      flushall(); 
      cout << endl; 

      talkto.message = 3; 

      //send request for user information packet 
      send(ClientSocket, (char *)&talkto, sizeof(struct Users), 0); 

      recv(ClientSocket, RxBuffer, sizeof(RxBuffer), 0); 

      memcpy(&temp, RxBuffer, sizeof(struct Users)); 

      //if message received is of type 4 (acknowledgement of user request info) 
      if (temp.message == 4) { 

       cout << "Requested User: " << temp.userName << endl << "Online status: " << temp.online << endl << endl; 
      } 
     } 

     //cout << temp.userName << endl << temp.online << endl << temp.message; 
    } 

} while (log != 2); 


closesocket(ClientSocket); 


WSACleanup(); 



} 

답변

1

당신은 루프 내부의 listen()을 사용하지 말아. accept() 만 또한 nonblocking socket을 사용하지 마십시오. 또 다른 점은 accept을 마칠 때마다 closesocket을 사용해야한다는 것입니다. 또한 recv()은 송신과 달리 모든 데이터를 수신하기 전에 리턴 할 수 있으므로 루프에서 처리해야합니다. 서버에 대한

귀하의 기본 구조 : 내가 계속 다른 연결을 찾고 있기 때문에

struct sockaddr_in inAddr; //incoming address. Use it to distinguise between incoming clients 
struct sockaddr_in address; 
unsigned int inLen; 
int recvMsgSize; 
unsigned short port = 20000; 
Socket socket_handle, acceptSocket; 

socket_handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
if(socket_handle == INVALID_SOCKET){ 
    //error 
} 

memset(&address, 0, sizeof(address)); 
address.sin_family = AF_INET; 
address.sin_addr.s_addr = htonl(INADDR_ANY); //All incoming addresses 
address.sin_port = htons(port); //port must be unsigned short not int! 
if(bind(socket_handle, (struct sockaddr *)&address, sizeof(address)) < 0){ 
    //error 
} 

if(listen(socket_handle, MAXPENDING) < 0){ 
    //error 
} 

while(true){ 
    acceptSocket = accept(socket_handle, (struct sockaddr *) &inAddr, &inLen)); 
    if(acceptSocket == INVALID_SOCKET){ 
     //error 
    } 

    while(true){ 
     recvMsgSize = recv(acceptSocket, received_data, strlen(received_data), 0); 
     if(recvMsgSize < 0){/*error*/} 
     else if(recvMsgSize == 0){break;} 
     else{/*receive your data*/} 
    } 

    (do other stuff...) 
    closesocket(acceptSocket); 
} 

closesocket(socket_handle); 
WSACleanup(); 

발터

+0

나는 while 루프를 필요로하고 그들은/뷰 정보를 로그온 할 mutliple 요청을 보냅니다. – user2981393

+0

@ user2981393 while 루프에 대한 답을 수정했습니다. 내 실수. –

+0

수신 대기열을 제거하고 accept를받은 다음 내 while 루프가 끝날 때 소켓을 닫습니다.하지만 클라이언트가 첫 번째 패킷 다음에 다른 패킷을 보내고 서버가이를 받아들이지 않는 것처럼 더 이상 새 패킷을 받아들이지 않습니다. – user2981393