2017-04-09 200 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(); 
    } 
    } 
}