2017-04-09 111 views
0

我有問題從UDP套接字接收消息。 我已經使C++服務器和客戶端應用程序正常工作。服務器從客戶端接收消息然後發回響應,客戶端收到消息,然後他們都關閉套接字並退出。現在我嘗試用C#創建客戶端程序,我無法接收來自服務器的消息。客戶端C#應用程序發送消息,然後C++ Server正確接收消息,但是當服務器發回他的響應時,客戶端無法接收它。我已經在本地虛擬機和VPS上測試過我的服務器,結果是一樣的。任何想法?C#UDP套接字無法接收消息

Server代碼C++:

#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <pthread.h> 

#define MSG "Hi i'm server" 
#define SERVERPORT "8642" 
#define MAXBUFLEN 100 


// Get sockaddr, IPv4 or IPv6. 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) 
    { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int LoginUser() 
{ 
    int locUserId = 0; 

    // Call DB. 

    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    // Load up address structs. 
    struct addrinfo hints, *res; 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // Use IPv4 or IPv6, whichever. 
    hints.ai_socktype = SOCK_DGRAM; // UDP. 
    hints.ai_flags = AI_PASSIVE; // Fill in my IP for me. 

    int locInitAddrInfo = getaddrinfo(NULL, SERVERPORT, &hints, &res); 

    if (locInitAddrInfo != 0) 
    { 
     printf("Error initialize address info: %s\n", gai_strerror(locInitAddrInfo)); 
     return 1; 
    } 

    printf("Address info initialized: %i\n", locInitAddrInfo); 

    // Initialize the socket. 
    int locInitSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 

    if (locInitSocket == -1) 
    { 
     printf("Error initialize socket: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     return 2; 
    } 

    printf("Socket initialized: %i\n", locInitSocket); 

    // Bind a name to a socket. 
    int locInitBind = bind(locInitSocket, res->ai_addr, res->ai_addrlen); 

    if (locInitBind == -1) 
    { 
     printf("Error bind socket: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     close(locInitSocket); 
     return 3; 
    } 

    printf("Socket binded: %i\n", locInitBind); 

    // Receive message from client. 
    char buf[MAXBUFLEN]; 
    struct sockaddr_storage their_addr; 
    socklen_t addr_len = sizeof their_addr; 

    int locNumByteRecv = recvfrom(locInitSocket, buf, MAXBUFLEN, 0, (struct sockaddr *)&their_addr, &addr_len); 

    if (locNumByteRecv == -1) 
    { 
     printf("Error receive from: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     close(locInitSocket); 
     return 4; 
    } 

    // ----------------------------------------- 
    char s[INET6_ADDRSTRLEN]; 

    printf("Server: got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s)); 
    printf("Server: packet is %d bytes long\n", locNumByteRecv); 
    buf[locNumByteRecv] = '\0'; 
    printf("Server: packet contains \"%s\"\n", buf); 
    // ----------------------------------------- 

    sleep(2); 

    // Send to client. 
    int locNumByteSend = sendto(locInitSocket, MSG, strlen(MSG), 0, (struct sockaddr *)&their_addr, addr_len); 

    if (locNumByteSend == -1) 
    { 
     printf("Error send to: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     close(locInitSocket); 
     return 5; 
    } 

    printf("Server: sent %d bytes to %s:%s\n", locNumByteSend, inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s), SERVERPORT); 

    // Free the linked-list. 
    freeaddrinfo(res); 

    // Close the socket. 
    close(locInitSocket); 

    printf("Socket closed.\nHave a nice day :)\n"); 

    return 0; 
} 

客戶端代碼C++:

#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define MSG "Hi i'm client" 
#define SERVERIP "192.168.1.33" 
#define SERVERPORT "8642" 
#define MAXBUFLEN 100 

// Get sockaddr, IPv4 or IPv6. 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) 
    { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(int argc, char *argv[]) 
{ 
    // Load up address structs. 
    struct addrinfo hints, *res; 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // Use IPv4 or IPv6, whichever. 
    hints.ai_socktype = SOCK_DGRAM; // UDP. 

    int locInitAddrInfo = getaddrinfo(SERVERIP, SERVERPORT, &hints, &res); 

    if (locInitAddrInfo != 0) 
    { 
     printf("Error initialize address info: %s\n", gai_strerror(locInitAddrInfo)); 
     return 1; 
    } 

    printf("Address info initialized: %i\n", locInitAddrInfo); 

    // Initialize the socket. 
    int locInitSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 

    if (locInitSocket == -1) 
    { 
     printf("Error initialize socket: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     return 2; 
    } 

    printf("Socket initialized: %i\n", locInitSocket); 

    // Send to server. 
    int locNumByteSend = sendto(locInitSocket, MSG, strlen(MSG), 0, res->ai_addr, res->ai_addrlen); 

    if (locNumByteSend == -1) 
    { 
     printf("Error send to: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     close(locInitSocket); 
     return 3; 
    } 

    printf("Client: sent %d bytes to %s:%s\n", locNumByteSend, SERVERIP, SERVERPORT); 

    // Receive message from server. 
    char buf[MAXBUFLEN]; 
    struct sockaddr_storage their_addr; 
    socklen_t addr_len = sizeof their_addr; 

    int locNumByteRecv = recvfrom(locInitSocket, buf, MAXBUFLEN, 0, (struct sockaddr *)&their_addr, &addr_len); 

    if (locNumByteRecv == -1) 
    { 
     printf("Error receive from: %s\n", strerror(errno)); 
     freeaddrinfo(res); 
     close(locInitSocket); 
     return 4; 
    } 

    // ----------------------------------------- 
    char s[INET6_ADDRSTRLEN]; 

    printf("Client: got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s)); 
    printf("Client: packet is %d bytes long\n", locNumByteRecv); 
    buf[locNumByteRecv] = '\0'; 
    printf("Client: packet contains \"%s\"\n", buf); 
    // ----------------------------------------- 

    // Free the linked-list. 
    freeaddrinfo(res); 

    // Close the socket. 
    close(locInitSocket); 

    printf("Socket closed.\nHave a nice day :)\n"); 

    return 0; 
} 

這裏是我的C#代碼不起作用:

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

namespace TestCSharpSocket 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       // This work fine ---------------------------- 
       IPEndPoint RemoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.33"), 8642); 
       Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
       string welcome = "Welcome"; 
       byte[] data = Encoding.ASCII.GetBytes(welcome); 
       server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint); 
       server.Close(); 

       Console.WriteLine("Welcome send"); 

       // End This work fine ---------------------------- 

       IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName()); 
       IPEndPoint ServerEndPoint = new IPEndPoint(IPAddress.Any, 8642); 
       Socket WinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
       WinSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000); 


       IPEndPoint sender = new IPEndPoint(IPAddress.Any, 8642); 
       EndPoint Remote = (EndPoint)(sender); 

       WinSocket.Bind(ServerEndPoint); 

       data = new byte[256]; 
       int recv = WinSocket.ReceiveFrom(data, ref Remote); 
       WinSocket.Close(); 


       Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); 
      } 
      catch (SocketException sex) 
      { 
       Console.WriteLine("Time Out: " + sex.ToString()); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

這裏是另一個C#代碼不起作用:

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

namespace TestCSharpSocket 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       // This work fine ---------------------------- 
       IPEndPoint RemoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.33"), 8642); 
       Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
       string welcome = "Welcome"; 
       byte[] data = Encoding.ASCII.GetBytes(welcome); 
       server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint); 
       server.Close(); 

       Console.WriteLine("Welcome send"); 

       // End This work fine ---------------------------- 

       UdpClient listener = new UdpClient(8642); 
       listener.Client.ReceiveTimeout = 5000; 
       IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 8642); 

       byte[] receivebytes; 
       receivebytes = listener.Receive(ref endpoint); 

       Console.WriteLine(Encoding.ASCII.GetString(receivebytes, 0, receivebytes.Length)); 
      } 
      catch (SocketException sex) 
      { 
       Console.WriteLine("Time Out: " + sex.ToString()); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 
+0

在您發送消息後請勿關閉'server'套接字。服務器將發送回覆到該套接字;如果關閉套接字,則無法收到回覆。如果你真的想用'UdpClient'來接收響應,你可以通過使用無參數構造函數並分配'Client'屬性來實現:'UdpClient listener = new UdpClient {Client = server};'。但在我看來,你應該跳過'UdpClient'並使用'server.ReceiveFrom()'接收回復。 –

回答

0

謝謝@Peter! 在我回顧我的代碼後,解決方案如下:

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

namespace TestCSharpSocket 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     try 
     { 
      // This work fine ---------------------------- 
      IPEndPoint RemoteEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.33"), 8642); 
      Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
      string welcome = "Welcome"; 
      byte[] data = Encoding.ASCII.GetBytes(welcome); 
      server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint); 

      Console.WriteLine("Welcome send"); 

      IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); 
      EndPoint Remote = (EndPoint)(sender); 

      data = new byte[256]; 
      int recv = server.ReceiveFrom(data, ref Remote); 
      server.Close(); 

      Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); 
     } 
     catch (SocketException sex) 
     { 
      Console.WriteLine("Time Out: " + sex.ToString()); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 

     Console.ReadLine(); 
    } 
    } 
}