2015-08-28 78 views
2

我遇到了一个问题,我认为这只是一个从unsigned char转换为char *的情况。但是,我没有设法以一种有效的方式来做到这一点!unsigned char char *从C++ WinSock客户端到C#服务器的无符号char *

我在做什么是读取数据作为一个无符号字符[64]的C + +程序。这就需要通过TCP套接字等待C#的TcpListener(我也试过用netcat在Linux上,并Hurcules听来传送。

侦听器(我用哪一个)接收任何有意义!
如果我得到的东西传输,但它是废话,当我在调试期间检查buffer2它只包含一个“0”。

下面是一些剥离的C++代码发送使用我自己的SocketClient_Winsock类(这是甚至更进一步下)

#include "stdafx.h" 
#include "SocketClient_Winsock.h" 
#include <iostream> 

using namespace std; 
void GetData(unsigned char *fillme) 
{ 

    // Fill the array! 
    for (int a = 0; a < 64; a++) 
    { 
     fillme[a] = a; 
    } 

    printf("in GetData: \n"); 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", fillme[a]); 
    printf("\n\n"); 


} 


void SendData(char* sendme) 
{ 
    printf("in SendData: \n"); 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", sendme[a]); 
    printf("\n\n"); 

    SocketClient_Winsock sock("127.0.0.1"); // Default constructor 127.0.0.1:5000 
    sock.Start(); 
    //sock.Send("Incoming!\n"); 
    sock.Send(sendme); 
    //sock.Send("Done."); 
    sock.Stop(); 


} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    // Create the buffer 
    unsigned char buffer[64]; 

    printf("Before filling: \n"); // output 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", buffer[a]); 
    printf("\n\n"); 

    // Fill the buffer 
    GetData(buffer);  

    printf("after filling: \n"); // output again 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", buffer[a]); 
    printf("\n\n"); 

    // Send data over TCP connection  
    SendData((char*)buffer); 

    // Output 
    printf("after sending: \n"); 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", buffer[a]); 
    printf("\n\n"); 

    return 0; 
} 

这里是SocketClient_Winsock.h:

#pragma once 
#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 
#include <string> 
#include <algorithm> 

// link with Ws2_32.lib 
#pragma comment(lib, "Ws2_32.lib") 
#pragma comment (lib, "Mswsock.lib") 
#pragma comment (lib, "AdvApi32.lib") 

#define DEFAULT_PORT "5000" 
#define DEFAULT_BUFLEN 512 
using namespace std; 
class SocketClient_Winsock 
{ 
private: 

    WSADATA wsaData; 
    SOCKET ConnectSocket = INVALID_SOCKET; 
    struct addrinfo *result = NULL, 
     *ptr = NULL, 
     hints; 
    //char *sendbuf = "this is a test"; // we expect this to be sent back from the class 
    char recvbuf[DEFAULT_BUFLEN]; 
    int iResult; 
    int recvbuflen = DEFAULT_BUFLEN; 


    char* serverName; 

public: 
    SocketClient_Winsock(); 
    SocketClient_Winsock(char* servername); 
    bool Start(); 
    int Stop(); 
    int Send(string); 
    int Send(char*); 
    int Send(unsigned char*); 
    bool Recv(); 

    ~SocketClient_Winsock(); 
}; 

而且SocketClient_Winsock.cpp:

#include "stdafx.h" 
#include "SocketClient_Winsock.h" 
#include <iostream> 
// From https://msdn.microsoft.com/en-us/library/windows/desktop/ms737591(v=vs.85).aspx 
SocketClient_Winsock::SocketClient_Winsock() 
{ 
    serverName = "127.0.0.1"; // Default to localhost 
} 
SocketClient_Winsock::SocketClient_Winsock(char * servername) 
{ 
    serverName = servername; 
    ConnectSocket = INVALID_SOCKET; 
} 
bool SocketClient_Winsock::Start() { 

    // Initialize Winsock 
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
    if (iResult != 0) { 
     printf("WSAStartup failed with error: %d\n", iResult); 
     return 1; 
    } 

    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 

    // Resolve the server address and port 
    iResult = getaddrinfo(serverName, DEFAULT_PORT, &hints, &result); 
    if (iResult != 0) { 
     printf("getaddrinfo failed with error: %d\n", iResult); 
     WSACleanup(); 
     return 1; 
    } 

    // Attempt to connect to an address until one succeeds 
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { 

     // Create a SOCKET for connecting to server 
     ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
      ptr->ai_protocol); 
     if (ConnectSocket == INVALID_SOCKET) { 
      printf("socket failed with error: %ld\n", WSAGetLastError()); 
      WSACleanup(); 
      return 1; 
     } 

     // Connect to server. 
     iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 
     if (iResult == SOCKET_ERROR) { 
      closesocket(ConnectSocket); 
      ConnectSocket = INVALID_SOCKET; 
      continue; 
     } 
     break; 
    } 

    freeaddrinfo(result); 

    if (ConnectSocket == INVALID_SOCKET) { 
     printf("Unable to connect to server!\n"); 
     WSACleanup(); 
     return 1; 
    } 


    return true; 
}; 

int SocketClient_Winsock::Stop() 
{ 
    // shutdown the connection since no more data will be sent 
    iResult = shutdown(ConnectSocket, SD_SEND); 
    if (iResult == SOCKET_ERROR) { 
     printf("shutdown failed with error: %d\n", WSAGetLastError()); 
     closesocket(ConnectSocket); 
     WSACleanup(); 
     return 1; 
    } 
    return 0; 
}; 

// Send message to server 
int SocketClient_Winsock::Send(char* msg) 
{ 

    printf("during sending: \n"); 
    for (int a = 0; a < 64; a++) 
     printf("%i, ", msg[a]); 
    printf("\n\n"); 

    iResult = send(ConnectSocket, msg, (int)strlen(msg), 0); 

    if (iResult == SOCKET_ERROR) { 
     printf("send failed with error: %d\n", WSAGetLastError()); 
     closesocket(ConnectSocket); 
     WSACleanup(); 
     return 1; 
    } 

    return 0; 
}; 



int SocketClient_Winsock::Send(std::string msg) 
{ 

    int iResult = send(ConnectSocket, msg.c_str(), msg.size(), 0); 

    if (iResult == SOCKET_ERROR) 
    { 
     printf("send failed: %d\n", WSAGetLastError()); 
     Stop(); 
     return false; 
    } 

    return 0; 
}; 

// Receive message from server 
bool SocketClient_Winsock::Recv() 
{ 
    char recvbuf[DEFAULT_BUFLEN]; 
    int iResult = recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0); 

    if (iResult > 0) 
    { 

     std::string msg = std::string(recvbuf); 

     msg.erase(msg.find_first_of("\n"), msg.length()); // remove all characters after /n 
     std::cout << msg << std::endl; 
     return true; 
    } 


    return false; 
} 
SocketClient_Winsock::~SocketClient_Winsock() 
{ 
    // cleanup 
    closesocket(ConnectSocket); 
    WSACleanup(); 
} 

和C#主持人:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using System.Net; 
using System.Net.Sockets; 
namespace Receiver 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // now listen: 
      Int32 port = 5000; 
      IPAddress localAddr = IPAddress.Parse("127.0.0.1"); 

      // TcpListener server = new TcpListener(port); 
      TcpListener server = new TcpListener(localAddr, port); 

      // Start listening for client requests. 
      server.Start(); 

      // Buffer for reading data 
      Byte[] bytes = new Byte[64]; 
      String data = null; 

      // Enter the listening loop. 
      while(true) 
      { 
       Console.Write("Waiting for a connection... "); 

       // Perform a blocking call to accept requests. 
       // You could also user server.AcceptSocket() here. 
       TcpClient client = server.AcceptTcpClient();    
       Console.WriteLine("Connected!"); 

       data = null; 

       // Get a stream object for reading and writing 
       NetworkStream stream = client.GetStream(); 

       int i; 

       // Loop to receive all the data sent by the client. 
       while((i = stream.Read(bytes, 0, bytes.Length))!=0) 
       { 
        // Translate data bytes to a ASCII string. 
        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); 


        Console.WriteLine("Received: {0}", data); 

        // Process the data sent by the client. 
        data = data.ToUpper(); 

        byte[] msg = System.Text.Encoding.ASCII.GetBytes(data); 


        // Send back a response. 
        //stream.Write(msg, 0, msg.Length); 
        //Console.WriteLine("Sent: {0}", data);    
       } 

       // Shutdown and end connection 
       client.Close(); 
      } 

      Console.WriteLine("\nHit enter to continue..."); 

      Console.Read(); 
     } 
    } 
} 
+2

C++的'char'是C#的'byte'所以'字符*'大致等于'字节* ''或'byte []'并且发布一些C#代码。 – Bauss

+0

C#结束是使用发布的byte [] ... C#代码。 – zotty

回答

1

由于MagikM18下面评论,最初的解决方案根本没有解决方案...只是一个bug的解决方法。

的错误是在事物的C#侧(我忽略了,以为是从MSDN,它会没事的。别这样!)。它将我的数据并将其强制转换为ASCII - 因此是无稽之谈。如果我查看原始数据一切都很好。

所以,我的发送数据现在看起来是这样的:

int SocketClient_Winsock::Send(char* msg, int msgLength) 
{ 
    iResult = send(ConnectSocket, msg, msgLength, 0); 
    if (iResult == SOCKET_ERROR) { 
     printf("send failed with error: %d\n", WSAGetLastError()); 
     closesocket(ConnectSocket); 
     WSACleanup(); 
     return 1; 
    } 

    return 0; 
}; 

,并通过调用: sock.Send((char*)buffer, BUFFER_LEN);

+1

你不应该这样做。你正在发送二进制数据,所以你不应该使用字符串类。现实是你的代码中有一个bug,这只是一个解决方法,而不是一个修复。这个错误在'Send(char *)'函数中,你清楚地认为数据是64字节,但是你使用'strlen'来获得WinSock的长度。这是行不通的,因为它假定字符串是文本而不是二进制的,所以它会在它找到的第一个零处完成,这不是意图;相反,你应该再次通过64。更好的解决方案是为消息长度添加一个参数。 –

+0

现货 - 我知道有些事情是不对的,但是到了我想要的东西并且发布它的时候。我现在已经回去修改了一个更合适的解决方案。 – zotty

+1

很高兴工作。只是供参考,下次请不要更新问题中的代码,因为它可能会混淆试图回答或查看其他答案的人;相反,更新您的答案或添加一个新的答案。 –