проблема с программированием сокетов в c \ c ++ - PullRequest
1 голос
/ 21 марта 2009
#include "stdafx.h"
#include <windows.h>
#include <winsock.h>
#include <stdio.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpCmdLine,int nCmdShow)
{
    WSADATA ws;
    char buf[100];

    WSAStartup(0x0101,&ws);

    sprintf(buf,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
    MessageBox(0,buf,"info",0);
    WSACleanup();
    return 0;
}

Эта программа предназначена для получения информации о доступной версии wsock на компьютере. Я не могу понять, почему "stdafx.h" включен в программу. Какое значение имеет APIENTRY? Разве мы не можем использовать _stdcall вместо этого? Я также не могу скомпилировать его в VC ++. В чем проблема с кодом?

Ниже приведены ошибки при выполнении программы, при компиляции ошибок нет.

--------------------Configuration: sa - Win32 Debug--------------------
Linking...
sa.obj : error LNK2001: unresolved external symbol _WSACleanup@0
sa.obj : error LNK2001: unresolved external symbol _WSAStartup@8
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/sa.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

sa.exe - 4 error(s), 0 warning(s)

Ответы [ 6 ]

8 голосов
/ 21 марта 2009
  1. stdafx используется для реализации предварительно скомпилированных заголовков в VC ++. Вы можете поместить туда заголовки вашей библиотеки, такие как windows.h и winsock.h и т. Д., И они будут компилироваться только один раз при каждом изменении stdafx.h.

  2. APIENTRY обычно является просто определением для __stdcall, но иногда оно определяется пустым (например, если __stdcall не поддерживается). Это сделает ваш код более переносимым.

  3. Без реальных ошибок, которые вы получаете, я не смогу сильно помочь. Но мое первое предположение заключается в том, что в вашей сборке включен юникод, и он жалуется, что MessageBoxW не принимает в качестве аргумента символ [100]. В этом случае либо используйте широкие символы везде, либо отключите юникод, либо используйте MessageBoxA, чтобы явно использовать версию ASCII.

Edit:

Теперь с ошибками все просто. Под Свойства проекта -> Компоновщик -> Ввод -> Дополнительные зависимости, добавьте ws2_32.lib. Таким образом, вы можете связать функции Winsock.

Отсутствующий _main означает, что вы создаете приложение как консольное приложение, а не как приложение для Windows. Вернитесь в Свойства проекта -> Линкер -> Система и установите для Подсистемы значение Windows (/ Подсистема: Windows) вместо Консоли. Или просто переименуйте WinMain в int main() (убедитесь, что вы сбросили APIENTRY).

Кроме того, если вы используете MSVC ++, вы также можете использовать более безопасный sprintf_s:

sprintf_s(buf,100,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
4 голосов
/ 21 марта 2009

Что касается ошибок: вам нужно создать ссылку на библиотеку ws2_32.lib. Вы можете сделать это двумя способами:

  1. Добавьте его в свойствах проекта -> Linker -> Input -> "дополнительные библиотеки" (не забудьте сделать это для конфигураций Debug и Release).
  2. Добавьте в свой заголовок директиву компилятора:

    # комментарий прагмы (lib, "ws2_32.lib")

Я предпочитаю второй метод, потому что сделанные вами изменения видны в источнике, а не скрыты глубоко в настройках проекта.

Что касается APIENTRY и аналогичных определений - это просто удобство, например, возвращать NULL вместо 0, чтобы указать, что вы ничего не возвращаете вместо нуля. Облегчает чтение и понимание кода.

0 голосов
/ 21 марта 2009

Если компоновщик жалуется, что не может найти _main, это означает, что он пытается связать вашу программу как консольное приложение, что означает, что вы должны определить main (), а не WinMain (). Если у вас есть WinMain (), вы, вероятно, должны создавать свое приложение как приложение Windows.

0 голосов
/ 21 марта 2009

Что касается ошибок компоновщика, вы должны ссылаться на wsock32.lib.

0 голосов
/ 21 марта 2009

попробуйте следующий
откройте свойства проекта, выберите свойства компоновщика, выберите подэлемент ввода и добавьте Ws2_32.lib в элемент дополнительных зависимостей. не забудьте сделать то же самое для всех конфигураций проекта.
также кажется, что вам нужно изменить использовать int main () вместо WinMain (...)

stdafx.h - обычно означает предварительно скомпилированные заголовочные проекты VC ++
APIENTRY - соглашение о вызовах. в вашем случае это __stdcall, но иногда может означать что-то другое.

0 голосов
/ 21 марта 2009

stdafx имеет отношение к предварительно скомпилированным заголовкам в visual studio. Он не имеет ничего общего с сокетом.

APIENTRY имеет отношение к соглашению о вызовах WinMain, опять же, оно не должно иметь ничего общего с сокетом.

Опубликовать ошибки.

...