⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32socketserver.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 2 页
字号:
  state_ = CS_CONNECTING;  return 0;}voidWin32Socket::OnSocketNotify(int event, int error) {  error_ = error;  switch (event) {    case FD_CONNECT:      if (error != ERROR_SUCCESS) {        ReportWSAError("WSAAsync:connect notify", error, addr_);#ifdef DEBUG        int32 duration = utils_base::TimeDiff(talk_base::GetMillisecondCount(),             connect_time_);        LOG(LS_INFO) << "WSAAsync:connect error (" << duration                     << " ms), faking close";#endif        Close();        // If you get an error connecting, close doesn't really do anything        // and it certainly doesn't send back any close notification, but        // we really only maintain a few states, so it is easiest to get        // back into a known state by pretending that a close happened, even        // though the connect event never did occur.        SignalCloseEvent(this, error);      } else {#ifdef DEBUG        int32 duration = utils_base::TimeDiff(utils_base::GetMillisecondCount(),             connect_time_);        LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";#endif        state_ = CS_CONNECTED;        SignalConnectEvent(this);      }      break;    case FD_ACCEPT:    case FD_READ:      if (error != ERROR_SUCCESS) {        ReportWSAError("WSAAsync:read notify", error, addr_);        Close();      } else {        SignalReadEvent(this);      }      break;    case FD_WRITE:      if (error != ERROR_SUCCESS) {        ReportWSAError("WSAAsync:write notify", error, addr_);        Close();      } else {        SignalWriteEvent(this);      }      break;    case FD_CLOSE:      ReportWSAError("WSAAsync:close notify", error, addr_);      Close();      SignalCloseEvent(this, error);      break;  }}voidWin32Socket::OnDnsNotify(int ip, int error) {  LOG_F(LS_INFO) << "(" << utils_base::SocketAddress::IPToString(ip)                 << ", " << error << ")";  if (error == 0) {    utils_base::SocketAddress address(ip, dns_->port);    sockaddr_in addr;    address.ToSockAddr(&addr);    error = DoConnect(addr);  } else {    Close();  }  if (error) {    error_ = error;    SignalCloseEvent(this, error_);  } else {    delete dns_;    dns_ = NULL;  }}intWin32Socket::GetError() const {  return error_;}voidWin32Socket::SetError(int error) {  error_ = error;}Socket::ConnState Win32Socket::GetState() const {  return state_;}int Win32Socket::SetOption(Option opt, int value) {  ASSERT(opt == OPT_DONTFRAGMENT);  value = (value == 0) ? 0 : 1;  return ::setsockopt(socket_, IPPROTO_IP, IP_DONTFRAGMENT,       reinterpret_cast<char*>(&value), sizeof(value));}intWin32Socket::Send(const void *pv, size_t cb) {  int sent = ::send(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0);  UpdateLastError();  return sent;}intWin32Socket::SendTo(const void *pv, size_t cb,     const utils_base::SocketAddress& addr) {  sockaddr_in saddr;  addr.ToSockAddr(&saddr);  int sent = ::sendto(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0,       (sockaddr*)&saddr, sizeof(saddr));  UpdateLastError();  return sent;}int Win32Socket::Recv(void *pv, size_t cb) {  int received = ::recv(socket_, (char *)pv, (int)cb, 0);  UpdateLastError();  if (signal_close_ && (received > 0)) {    char ch;    if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) {      signal_close_ = false;      ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,                    WSAMAKESELECTREPLY(FD_CLOSE, 0), 0);    }  }  return received;}intWin32Socket::RecvFrom(void *pv, size_t cb, utils_base::SocketAddress *paddr) {  sockaddr_in saddr;  socklen_t cbAddr = sizeof(saddr);  int received = ::recvfrom(socket_, (char *)pv, (int)cb, 0, (sockaddr*)&saddr,                            &cbAddr);  UpdateLastError();  if (received != SOCKET_ERROR)    paddr->FromSockAddr(saddr);  if (signal_close_ && (received > 0)) {    char ch;    if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) {      signal_close_ = false;      ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,                    WSAMAKESELECTREPLY(FD_CLOSE, 0), 0);    }  }  return received;}int Win32Socket::Listen(int backlog) {  int err = ::listen(socket_, backlog);  UpdateLastError();  if (err == 0)    state_ = CS_CONNECTING;  return err;}utils_base::Socket* Win32Socket::Accept(utils_base::SocketAddress *paddr) {  sockaddr_in saddr;  socklen_t cbAddr = sizeof(saddr);  SOCKET s = ::accept(socket_, (sockaddr*)&saddr, &cbAddr);  UpdateLastError();  if (s == INVALID_SOCKET)    return NULL;  if (paddr)    paddr->FromSockAddr(saddr);  Win32Socket* socket = new Win32Socket;  if (0 == socket->Attach(s))    return socket;  delete socket;  return NULL;}int Win32Socket::Close() {  int err = 0;  if (socket_ != INVALID_SOCKET) {    err = ::closesocket(socket_);    socket_ = INVALID_SOCKET;    signal_close_ = false;    UpdateLastError();  }  if (dns_) {    WSACancelAsyncRequest(dns_->handle);    delete dns_;    dns_ = NULL;  }  if (sink_) {    sink_->Dispose();    sink_ = NULL;  }  memset(&addr_, 0, sizeof(addr_));        // no longer connected, zero ip/port  state_ = CS_CLOSED;  return err;}int Win32Socket::EstimateMTU(uint16* mtu) {  utils_base::SocketAddress addr = GetRemoteAddress();  if (addr.IsAny()) {    error_ = ENOTCONN;    return -1;  }  utils_base::WinPing ping;  if (!ping.IsValid()) {    error_ = EINVAL; // can't think of a better error ID    return -1;  }  for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {    int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;    utils_base::WinPing::PingResult result =      ping.Ping(addr.ip(), size, 0, 1, false);    if (result == utils_base::WinPing::PING_FAIL) {      error_ = EINVAL; // can't think of a better error ID      return -1;    }    if (result != utils_base::WinPing::PING_TOO_LARGE) {      *mtu = PACKET_MAXIMUMS[level];      return 0;    }  }  ASSERT(false);  return 0;}boolWin32Socket::Create(long events) {  ASSERT(NULL == sink_);  if (INVALID_SOCKET == socket_) {    socket_ = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, 0);    if (socket_ == INVALID_SOCKET) {      UpdateLastError();      return false;    }  }  // Create window  sink_ = new EventSink(this);  sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10);  // start the async select  if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events)      == SOCKET_ERROR) {    UpdateLastError();    Close();    return false;  }  return true;}voidWin32Socket::UpdateLastError() {  error_ = WSAGetLastError();}///////////////////////////////////////////////////////////////////////////////// Win32SocketServer///////////////////////////////////////////////////////////////////////////////static UINT s_wm_wakeup_id;LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);// A socket server that provides cricket base services on top of a win32 gui threadWin32SocketServer::Win32SocketServer(MessageQueue *message_queue) {  if (s_wm_wakeup_id == 0)    s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");  message_queue_ = message_queue;  hwnd_ = NULL;  CreateDummyWindow();}Win32SocketServer::~Win32SocketServer() {  if (hwnd_ != NULL) {    KillTimer(hwnd_, 1);    ::DestroyWindow(hwnd_);  }}Socket* Win32SocketServer::CreateSocket(int type) {  ASSERT(SOCK_STREAM == type);  return new Win32Socket;}AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {  ASSERT(SOCK_STREAM == type);  return new Win32Socket;}bool Win32SocketServer::Wait(int cms, bool process_io) {  ASSERT(!process_io || (cms == 0));  // Should only be used for Thread::Send, or in Pump, below  if (cms == -1) {    MSG msg;    GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);  } else if (cms != 0) {    Sleep(cms);  }  return true;}void Win32SocketServer::WakeUp() {  // Always post for every wakeup, so there are no  // critical sections  if (hwnd_ != NULL)    PostMessage(hwnd_, s_wm_wakeup_id, 0, 0);}void Win32SocketServer::Pump() {  // Process messages  Message msg;  while (message_queue_->Get(&msg, 0))    message_queue_->Dispatch(&msg);  // Anything remaining?  int delay = message_queue_->GetDelay();  if (delay == -1) {    KillTimer(hwnd_, 1);  } else {    SetTimer(hwnd_, 1, delay, NULL);  }}void Win32SocketServer::CreateDummyWindow(){  static bool s_registered;  if (!s_registered) {    ::WNDCLASSW wc;    memset(&wc, 0, sizeof(wc));    wc.cbWndExtra = sizeof(this);    wc.lpszClassName = L"Dummy";    wc.lpfnWndProc = DummyWndProc;    ::RegisterClassW(&wc);    s_registered = true;  }  hwnd_ = ::CreateWindowW(L"Dummy", L"", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);  SetWindowLong(hwnd_, GWL_USERDATA, (LONG)(LONG_PTR)this);}LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp){  if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {    Win32SocketServer *ss = (Win32SocketServer *)(LONG_PTR)GetWindowLong(hwnd, GWL_USERDATA);    ss->Pump();    return 0;  }  return ::DefWindowProc(hwnd, wm, wp, lp);}} // namespace talk_base

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -