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();
}
}
}
在您发送消息后请勿关闭'server'套接字。服务器将发送回复到该套接字;如果关闭套接字,则无法收到回复。如果你真的想用'UdpClient'来接收响应,你可以通过使用无参数构造函数并分配'Client'属性来实现:'UdpClient listener = new UdpClient {Client = server};'。但在我看来,你应该跳过'UdpClient'并使用'server.ReceiveFrom()'接收回复。 –