如何从c#上的客户端服务器接收数据?

时间:2018-04-21 17:49:59

标签: c# c++ server client winsock

我正在做一个小游戏。 C ++上的服务器和基于C#的客户端。我有数据接收问题,我没有正确理解它是如何工作的,我需要第二个插座接收吗?或者第一个插座连接并可以同时接收?这是客户端

public class Connection
{
    static private string ip = "127.0.0.1";
    static private int port = 54000;

    static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   // static Socket acpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    public static void connectToServer()
    {
        socket.Connect(ip, port);

    }

    public static void sendData(byte[] buffer)
    {
        socket.Send(buffer);
    }

    public static byte[] encodeMessage(string message)
    {
        byte[] bf = Encoding.ASCII.GetBytes(message);
        return bf;
    }

    public static void recvData()
    {
        byte[] buf = new byte[256];
        byte[] copy = new byte[256];

        try
        {
            socket.Receive(buf);
        }
        catch (Exception e)
        {
            Console.WriteLine("Error");
        }

        if (buf != copy)
        {
            Console.WriteLine(Encoding.ASCII.GetChars(buf).ToString());

            buf = copy;
        }
    }

}

这是服务器:

int main() {

//init sock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);

int wsok = WSAStartup(ver, &wsData);
if (wsok != 0) {
    cerr << "Error while init\n";
    return 0;
}

//create
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
    cerr << "Error while creating\n";
    return 0;
}

//bind
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY;

bind(listening, (sockaddr*)&hint, sizeof(hint));

//tell winsock that the socket is for listen
listen(listening, SOMAXCONN);


fd_set master;

FD_ZERO(&master);
FD_SET(listening, &master);

while (true) {
    fd_set copy = master;

    int socketCount = select(0, &copy, nullptr, nullptr, nullptr);

    for (int i = 0; i < socketCount; i++) {
        SOCKET sock = copy.fd_array[i];
        if (sock == listening) {
            //accept connection
            SOCKET client = accept(listening, nullptr, nullptr);

            //add connection to list(&master)
            FD_SET(client, &master);

            //send welcome msg to connected client
            string welcomeMsg = "Your connected!";
            send(client, welcomeMsg.c_str(), welcomeMsg.size() + 1, 0);
        }
        else{

            //accept message
            char buf[32];
            ZeroMemory(buf, 32);
            string str;
            int cnt = 0;
            int bytesIn = recv(sock, buf, 32, 0);

            for (int i = 0; i < sizeof(buf); i++) {
                if (buf[i] != '0') {
                    content[cnt] = buf[i];
                    cnt++;
                }
            }
            if (bytesIn <= 0) {
                closesocket(sock);
                FD_CLR(sock, &master);
            }
            else {
                for (int i = 0; i < sizeof(buf); i++) {
                    cout << content[i];
                }
                for (int i = 0; i < master.fd_count; i++) {
                    SOCKET outSock = master.fd_array[i];
                    if (outSock != listening && outSock != sock) {
                        send(outSock, content, cnt, 0);
                        cout << "Message Send..." << endl;
                    }
                } 
            }
        }
    }

}

我有计时器,我调用recvData()。问题是连接后它返回&#34;你已经连接了!&#34;但之后它只是卡住了,不起作用。如果我评论Socket.Receive我没有问题,但我需要这个接收。感谢

1 个答案:

答案 0 :(得分:0)

您不必使用第二个套接字来接收数据,但SendReceive是同步函数,因此线程会被阻塞,直到当前操作完成其工作。对于接收,套接字必须至少接收字节以便解除对应用程序的阻塞。如果没有可用数据,Receive将无限期地等待,除非您使用ReceiveTimeout属性指定超时。 要避免阻塞部分,请使用异步函数BeginReceiveBeginSendMSDN有一个完整的服务器 - 使用异步套接字的客户端示例。