winsock实现UDP通信DEMO

来源:互联网 发布:win10的80端口被占用 编辑:程序博客网 时间:2024/05/24 04:14

Client

#define _WINSOCK_DEPRECATED_NO_WARNINGS#include <iostream>#include <string>#include <vector>#include <list>#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")namespace udp_client {class UdpClient {public:  bool InitWinsock() {    WSADATA wsa_data;    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {      std::cout << "Failed to link winsock.dll!" << std::endl;      return false;    }    return true;  }  void ReleaseWinsock() {    WSACleanup();  }  void set_port(u_short port) {    port_ = port;  }  void set_ip(const std::string& ip) {    ip_ = ip;  }  bool Start() {    SOCKET client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (client_socket == SOCKET_ERROR) {      std::cout << "Failed to create socket!" << std::endl;      return false;    }    sockaddr_in client_addr;    memset(&client_addr, 0, sizeof(sockaddr_in));    client_addr.sin_family = AF_INET;    client_addr.sin_port = htons(port_);    client_addr.sin_addr.S_un.S_addr = inet_addr(ip_.c_str());    const char* kGreeting = "Hello I'm client!";    int ret = sendto(client_socket, kGreeting, strlen(kGreeting), 0, (sockaddr*)&client_addr, sizeof(sockaddr));    if (ret == 0) {      std::cout << "Failed to send!" << std::endl;      return false;    }    const int kBufSize = 1048;    char buf[kBufSize] = {};    sockaddr_in server_addr = { 0 };    int server_addr_len = sizeof(sockaddr_in);    ret = recvfrom(client_socket, buf, kBufSize, 0, (sockaddr*)&server_addr, &server_addr_len);    std::cout << "Receive msg: " << buf << ". IP: " << inet_ntoa(server_addr.sin_addr)      << " Port: " << ntohs(server_addr.sin_port) << std::endl;    closesocket(client_socket);    return true;  }private:  u_short port_;  std::string ip_;};}  // udp_client#define PORT 6000#define IP "127.0.0.1"int main() {  using namespace udp_client;  UdpClient client;  if (!client.InitWinsock()) {    return 1;  }  client.set_port(PORT);  client.set_ip(IP);  client.Start();  client.ReleaseWinsock();  return 0;}



Server

#define _WINSOCK_DEPRECATED_NO_WARNINGS#include <iostream>#include <string>#include <vector>#include <list>#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")// 1.TCP是面向连接的,它在通信之前需要进行三次握手来确定双方是否已经准备好了。// 因此,双方很清楚数据是从哪里来的。// 而UDP是面向数据包的,因此就好像寄快递一样,你必须在快递上写一张纸条,上面填好姓名,// 地址等信息,填好之后,接收者才知道该东西是由谁寄过来的。// 而UDP的收发函数recvform和sendto了sockaddr结构的地址,用于保存从哪里发来的和发送到哪里的地址信息。// 2.UDP套接口是无连接的、不可靠的数据报协议;既然他不可靠为什么还要用呢?// 其一:当应用程序使用广播或多播时只能使用UDP协议;其二:由于他是无连接的,所以速度快。// 因为UDP套接口是无连接的,如果一方的数据报丢失,那另一方将无限等待,解决办法是设置一个超时。// 建立UDP套接口时socket函数的第二个参数应该是SOCK_DGRAM,说明是建立一个UDP套接口;// 由于UDP是无连接的,所以服务器端并不需要listen或accept函数。namespace udp_server {class UdpServer {public:  bool InitWinsock() {    WSADATA wsa_data;    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {      std::cout << "Failed to link winsock.dll!" << std::endl;      return false;    }    return true;  }  void ReleaseWinsock() {    WSACleanup();  }  void set_port(u_short port) {    port_ = port;  }  bool Start() {    SOCKET server_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (server_socket == SOCKET_ERROR) {      std::cout << "Failed to create socket!" << std::endl;      return false;    }    sockaddr_in server_addr;    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(port_);    server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr));    const int kBufSize = 1048;    char buf[kBufSize] = {};    while (true) {      memset(buf, 0, kBufSize);      // 用来保存客户端的网络信息。      sockaddr_in client_addr;      memset(&client_addr, 0, sizeof(sockaddr_in));      int client_addr_len = sizeof(sockaddr);      // 接收客户端发来的信息,server阻塞在这里,等待client发来报文。      int ret = recvfrom(server_socket, buf, kBufSize, 0, (sockaddr*)&client_addr, &client_addr_len);      std::cout << "Receive msg: " << buf << " from IP:[" << inet_ntoa(client_addr.sin_addr)                << "], Port:[" << ntohs(client_addr.sin_port) << "]" << std::endl;      // 发送数据给客户端。      const char* kGreeting = "Hello, I'm server!";      sendto(server_socket, kGreeting, strlen(kGreeting), 0, (sockaddr*)&client_addr, client_addr_len);    }    closesocket(server_socket);    return true;  }private:  u_short port_;};}  // udp_server#define PORT 6000int main2() {  using namespace udp_server;  UdpServer server;  if (!server.InitWinsock()) {    return 1;  }  server.set_port(PORT);  server.Start();  server.ReleaseWinsock();  return 0;}



原创粉丝点击