내가 게시 한 기능이 클라이언트와 서버간에 공유되어야한다고 가정합니다. 이를 달성하기 위해서는 약간 수정해야합니다. 예 : 서버 측에서 recvudp
은 나중에 메시지를 다시 보내는 데 필요한대로 클라이언트 주소 (가능하면 out 매개 변수)를 반환해야합니다. 또한 클라이언트 주소 구조가 이미 채워져 있으므로 (서버 측의 recvudp
또는 클라이언트 측의 수동으로) sendudp
을 인수로 전달할 수 있습니다.
Visual Studio 2010에서는 두 가지 간단한 프로젝트 (UDP 서버 및 클라이언트)를 만들었습니다. 둘 다 위에서 언급 한 공유 기능을 사용합니다. 이 코드는 완벽하지 않으며 기본적인 UDP 소켓 통신 만 보여줍니다.
Shared.h :
#ifndef SHARED_H
#define SHARED_H
#include <winsock2.h>
#include <string>
int udpsock(int port, const char* addr);
std::string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize);
int sendudp(std::string str, sockaddr_in dest, int sock);
#endif
Shared.cpp :
#include "Include\shared.h" // path to header - you might use different one
#include <iostream>
using namespace std;
int udpsock(int port, const char* addr)
{
int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (handle < 1)
return -1;
sockaddr_in address;
address.sin_family = AF_INET;
if (addr == INADDR_ANY)
address.sin_addr.s_addr = INADDR_ANY;
else
address.sin_addr.s_addr = inet_addr(addr);
address.sin_port = htons((unsigned short) port);
if (bind(handle, (const sockaddr*) &address, sizeof(sockaddr_in)) < 0)
return -1;
return handle;
}
// function should return sender address info (for the code the server)
string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize)
{
// TODO: use std::vector<char> here instead of char array
char* buf = 0;
buf = new char[size];
int retsize = recvfrom(sock, buf, size, 0, (sockaddr*) &SenderAddr, &SenderAddrSize);
if(retsize == -1)
{
cout << "\nRecv Error : " << WSAGetLastError();
if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == 0)
{
return "";
}
return "\0";
}
else if (retsize < size)
{
buf[retsize] = NULL;
}
string str(buf);
delete[] buf;
return str;
}
// On the client side, prepare dest like this:
// sockaddr_in dest;
// dest.sin_family = AF_INET;
// dest.sin_addr.s_addr = inet_addr(ip.c_str());
// dest.sin_port = htons(port);
int sendudp(string str, sockaddr_in dest, int sock)
{
int ret = sendto(sock,str.c_str(),str.size(),0, (sockaddr*)&dest,sizeof(dest));
if (ret == -1)
{
cout << "\nSend Error Code : " << WSAGetLastError();
}
return ret;
}
서버 : MAIN.CPP :
#include <winsock2.h>
#include <string.h>
#include <iostream>
#include "..\Shared\Include\shared.h"
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define SERVER_PORT 27015
#define MAX_MSG 1024
using namespace std;
int main(int argc, char *argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
sock = udpsock(SERVER_PORT, "127.0.0.1");
cout << "Waiting for datagram on port: " << SERVER_PORT << endl;
while(1)
{
sockaddr_in clientAddr;
// receive message
int clientAddrLen = sizeof(clientAddr);
cout << "Received message from the client: " << recvudp(sock, MAX_MSG, clientAddr, clientAddrLen) << endl;
sendudp("Hello from server!", clientAddr, sock);
}
WSACleanup();
return 0;
}
클라이언트 : MAIN.CPP :
#include <winsock2.h>
#include <iostream>
#include "..\Shared\Include\shared.h"
using namespace std;
#define MAX_MSG 1024
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
SOCKET sock = INVALID_SOCKET;
// Create a socket for sending data - it does not need to be binded like listening socket!
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sock == INVALID_SOCKET)
{
cout << socket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
unsigned short Port = 27015;
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(Port);
sendudp("Hello from client!", dest, sock);
sockaddr_in RecvAddr;
int recvaddrlen = sizeof(RecvAddr);
cout << "Received message from the server: " << recvudp(sock, MAX_MSG, RecvAddr, recvaddrlen) << endl;
cout << "Closing socket..." << endl;
nResult = closesocket(sock);
if(nResult == SOCKET_ERROR)
{
cout << "closesocket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
당신이 클라이언트를 실행하면
두 번 출력은 다음과 같습니다
서버 :
포트에 데이터 그램을 기다리는 : 27015
수신 된 메시지를 클라이언트에서 : 안녕하세요 클라이언트에서!
클라이언트로부터받은 메시지 : 안녕하세요.
클라이언트 :
안녕하세요 서버!
닫기 소켓 ...
UDP는 비 연결 프로토콜, 서버는 단지 데이터 (데이터 그램) 즉시, connect()
/accept()
와 연결 설정 (예 : 필요가 같이 존재하지를 보낼 수 UDP 포트와 클라이언트에서 음악을 감상 할 필요가있다 TCP).
UDP가 연결되어 있지 않아 연결할 수 없습니다.요청을 처리하고 sendto를 사용하여 전송합니다. UDP 클라이언트는 또한 서버 데이터를 받기 위해 서버 여야합니다 ... – neagoegab
UDP 소켓에서 connect()를 호출하여 "연결"할 수 있습니다. 하지만 실제로는 TCP 의미의 연결이 아닙니다. send()를 호출 할 때 패킷을 보낼 IP 주소를 네트워크 스택에 알려주는 숨겨진 변수를 설정하는 것과 같습니다. 아마도 sendto()가 잘 작동하고 이해하기가 쉽기 때문에 아마 신경 쓰지 않아도 될 것입니다. –