Как получить данные с сервера с клиентом на c #?

Ordec спросил: 28 марта 2018 в 04:09 в: c#

Я делаю небольшую игру. Сервер на 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 (). Проблема в том, что после подключения возвращается "You're Connected!" но после этого он просто застрял, не работает. Если я прокомментирую Socket.Receive, у меня нет проблем, но мне нужно это получение. Благодаря

1 ответ

CynicalSection ответил: 28 марта 2018 в 04:52

Вам не нужно использовать второй сокет для получения данных, но Send и Receive являются синхронными функциями, поэтому поток блокируется, пока текущая операция не завершит свою работу , Для получения сокет должен получить хотя бы байт, чтобы разблокировать приложение. Если данные недоступны, Receive будет ждать неопределенно долго, пока вы не укажете время ожидания с помощью свойства ReceiveTimeout. Чтобы избежать блокирующей части, используйте асинхронные функции BeginReceive и . MSDN имеет полный сервер - пример клиента с использованием асинхронных сокетов.