переделать под windows

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by al072, 17 Feb 2010.

  1. al072

    al072 New Member

    Joined:
    25 May 2008
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    Всем привет! проблема такая, клиент-серверное приложение было изначально написано под unix. я решил переделать его под windows! приложение реализовано на winsock. соответственно поменял заголовочные файлы, переписал функции! из 15 ошибок, которые выдавал компилятор остались 1 предупреждение и одна ошибка следующего содержания:

    1) warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
    2) error C2664: 'recv' : cannot convert parameter 2 from 'char (*)[21]' to 'char *'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    вот код программы (пишу в VS2008 на С++):

    Code:
    #define _CRT_SECURE_NO_WARNINGS 1 
    #include <winsock.h>
    #pragma comment (lib,"WSock32.Lib")
    #include <iostream>
    
    //extern errno;     //глобальная переменная, которая хранит код последней ошибки
    
    //проверка, задан ли шаблон INADDR_NONE, который обозначает сразу все доступные сетевые интерфейсы
    //на некоторых платформах, он может быть не задан.
    #ifndef INADDR_NONE
    #define INADDR_NONE 0xfffffffff
    #endif
    
    //функция создания и связывания сокета. объявление
    //аргументы:
    //port - порт, с которым связывается сервер
    //transport - протокол, по которому будет работать сервер (tcp или udp)
    //qlen - длина  очереди
    int sock(const char *port, const char *transport, int qlen);
    
    //главная функция
    int main()
    {
        int msock, csock;                //дескрипторы сокетов
        struct sockaddr_in  remaddr;            //структура IP-адреса клиента
        unsigned int remaddrs = sizeof(remaddr);    //размер структуры адреса
        char msg[21];                    //буфер сообщения
        
        msock = sock("1231", "tcp", 5);    //создаем tcp сокет и привязываем его к порту 3123, задав очередь 5
        if(msock < 0)            //проверяем значение дескриптора сокета
            return -1;        //завершаем программу
    
        while(1)    //бесконечный цикл
        {
            csock = accept(msock, (struct sockaddr*) &remaddr, &remaddrs);    //принимаем входящее подключение, адрес клиента в remaddr
            if(csock < 0)        //проверяем результат
                printf("Ошибка принятия подключения: %s\n", strerror(errno)); //сообщение об ошибке
            else            //если все нормально - начинаем обмен данными с клиентом
                {
                    if(recv(csock, msg, sizeof(msg),0) >0 )        //пробуем читать данные от клиента
                    {
                        if(strstr(msg, "hello"))            //если получено "hello"
                        {
                            memset(msg, 0, sizeof(msg));            //обнуляем буфер
                            strcpy(msg, "hello, ");                //формируем строку ответа
                            strcat(msg, inet_ntoa(remaddr.sin_addr));    //преобразовываем адрес клиента в строку
                            strcat(msg, " !!!\n\0");            //завершаем строку ответа
                            send(csock, msg, sizeof(msg),0);            //отсылаем ответ
                        }
                    }
                    closesocket(csock);        //закрываем сокет клиента
                }
        }    
        closesocket(msock);        //закрываем сокет сервера
        return 0;
    }
    //функция создания и связывания сокета. реализация
    int sock(const char *port, const char *transport, int qlen)
    {
        struct protoent *ppe;        
        struct sockaddr_in sin;
        int s, type;
        //обнуляем структуру адреса
        memset(&sin, 0, sizeof(sin));
        //указываем тип адреса - IPv4, для IPv6 необходимо указать AF_INET6
        sin.sin_family = AF_INET;
        //указываем, в качестве адреса, шаблон INADDR_ANY - все сетевые интерфейсы
        sin.sin_addr.s_addr = INADDR_ANY;
        //задаем порт
        sin.sin_port = htons((unsigned short)atoi(port));
        //преобразовываем имя транспортного протокола в номер протокола
        if((ppe = getprotobyname(transport)) == 0)
            {
                printf("Ошибка преобразования имени транспортного протокола: %s\n", strerror(errno));    //в случае неудачи выводим сообщение ошибки
                return -1;        
            }
        //используем имя протокола для определения типа сокета     
        if(strcmp(transport, "udp") == 0)
            type = SOCK_DGRAM;
        else
            type = SOCK_STREAM;    
        //создаем сокет
        s = socket(PF_INET, type, ppe->p_proto);
        if(s < 0)
            {
                printf("Ошибка создания сокета: %s\n", strerror(errno));    //в случае неудачи выводим сообщение ошибки
                return -1;
            }
        //привязка сокета с проверкой результата
        if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
            {
                printf("Ошибка связывания сокета: %s\n", strerror(errno));    //в случае неудачи выводим сообщение ошибки
                return -1;
            }
        //запуск прослушивания с проверкой результата
        if(type == SOCK_STREAM && listen(s, qlen) <0)
            {
                printf("Ошибка прослушивания сокета: %s\n", strerror(errno));    //в случае неудачи выводим сообщение ошибки
                return -1;
            }
        return s;    //возвращаем дескриптор сокета
    }
     
    #1 al072, 17 Feb 2010
    Last edited: 2 Mar 2010
  2. hs_alex

    hs_alex New Member

    Joined:
    13 Jul 2007
    Messages:
    22
    Likes Received:
    2
    Reputations:
    0
    1) warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

    Тебе предлагается использовать strerror_s вместо strerror.

    2) error C2664: 'recv' : cannot convert parameter 2 from 'char (*)[21]' to 'char *'

    В параметрах recv, перед второй переменной напиши (CHAR *), чтобы привести твою переменную типа char[21] к типу, который требуется в функции.

    Ошибки выдаются для кода, который отсутствует в посте.

    Good Luck!
     
  3. al072

    al072 New Member

    Joined:
    25 May 2008
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    код на который ругается компилятор присутствует в посте, вот фрагмент:
    Code:
    if(recv(csock,&msg, sizeof(msg),0) >0 )		//пробуем читать данные от клиента
    				{
    					if(strstr(msg, "hello"))			//если получено "hello"
    					{
    						memset(&msg, 0, sizeof(msg));			//обнуляем буфер
    						strcpy(msg, "hello, ");				//формируем строку ответа
    						strcat(msg, inet_ntoa(remaddr.sin_addr));	//преобразовываем адрес клиента в строку
    						strcat(msg, " !!!\n\0");			//завершаем строку ответа
    						send(csock, msg, sizeof(msg),0);			//отсылаем ответ
    					}
    				}
    попробовал привести к типу (char*), таким образом, которым вы посоветовали, компилятор выдал 8 предупреждений и 2 ошибки:

    error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup

    fatal error LNK1120: 1 unresolved externals

    warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

    warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

    warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

    warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

    warning C4996: 'strerror': This function or variable may be unsafe. Consider using strerror_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
     
  4. arpm

    arpm New Member

    Joined:
    6 Apr 2008
    Messages:
    8
    Likes Received:
    4
    Reputations:
    4
    http://forum.antichat.ru/showthread.php?p=674960#post674960
     
    1 person likes this.
  5. hs_alex

    hs_alex New Member

    Joined:
    13 Jul 2007
    Messages:
    22
    Likes Received:
    2
    Reputations:
    0
    Откорректировал:
    1. #pragma comment(lib, "WSock32.Lib")
    2. if(recv(csock, msg, sizeof(msg),0) >0 )

    Откомпилировал у себя в 2008 Express Edition - все ОК.

    Пробуй.
     
  6. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,309
    Reputations:
    327
    strcat и тд меняй на lstrcat и тд если не хочешь рантайм использовать, также ignore all default libraries, "ENTRY:WinMain" и поскакали и поскакали)
     
  7. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,309
    Reputations:
    327
    вот так без црт но придется ручками дописывать

    Code:
    #include <winsock2.h>
    #pragma optimize("gsy", on) 
    #pragma comment(linker, "/ENTRY:WinMain")
    
    // добавь в проекте либы: ntdll.lib ws2_32.lib
    
    int errn;     //глобальная переменная, которая хранит код последней ошибки
    
    //функция создания и связывания сокета. объявление
    //аргументы:
    //port - порт, с которым связывается сервер
    //transport - протокол, по которому будет работать сервер (tcp или udp)
    //qlen - длина  очереди
    int sock(const char *port, const char *transport, int qlen);
    
    HANDLE ghStdOut;
    
    //////////////////////////////////////////////////////////////////////////
    char *cstrerror(int code)
    {
    	static char errbuf[512];
    
    	// ... parse error
    
    	return errbuf;
    }
    
    //////////////////////////////////////////////////////////////////////////
    VOID cprintf(LPCSTR fmt...)
    {
    	DWORD dwCount;
    
    	va_list vl;
    	char msg[1024];
    
    	va_start(vl,fmt);
    	wvsprintf(msg,fmt,vl);
    	va_end(vl);
    
    	WriteConsole( ghStdOut, msg, lstrlen(msg), &dwCount, NULL);
    }
    
    
    //////////////////////////////////////////////////////////////////////////
    //главная функция
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
    	int msock, csock;                //дескрипторы сокетов
    	struct sockaddr_in  remaddr;            //структура IP-адреса клиента
    	unsigned int remaddrs = sizeof(remaddr);    //размер структуры адреса
    	char msg[21];                    //буфер сообщения
    
    	WSADATA wsd; // init winsock
    	WSAStartup(0x202, &wsd);
    
    	// get console
    	AllocConsole();
    	ghStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    	SetConsoleTextAttribute(ghStdOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
    
    	msock = sock("1231", "tcp", 5);    //создаем tcp сокет и привязываем его к порту 3123, задав очередь 5
    	if(msock < 0)            //проверяем значение дескриптора сокета
    		return -1;        //завершаем программу
    
    	while(1)    //бесконечный цикл
    	{
    		csock = accept(msock, (struct sockaddr*) &remaddr, (int*)&remaddrs);    //принимаем входящее подключение, адрес клиента в remaddr
    		if(csock < 0)        //проверяем результат
    			cprintf("Ошибка принятия подключения: %s\n", cstrerror(errn)); //сообщение об ошибке
    		else            //если все нормально - начинаем обмен данными с клиентом
    		{
    			if(recv(csock, &msg[0], sizeof(msg),0) >0 )        //пробуем читать данные от клиента
    			{
    			//	if(strstr(msg, "hello"))            //если получено "hello"
    				if(!lstrcmp(msg,"hello"))
    				{
    					memset(&msg, 0, sizeof(msg));            //обнуляем буфер
    					lstrcpy(msg, "hello, ");                //формируем строку ответа
    					lstrcat(msg, inet_ntoa(remaddr.sin_addr));    //преобразовываем адрес клиента в строку
    					lstrcat(msg, " !!!\n\0");            //завершаем строку ответа
    					send(csock, msg, sizeof(msg),0);            //отсылаем ответ
    				}
    			}
    			closesocket(csock);        //закрываем сокет клиента
    		}
    	}    
    	closesocket(msock);        //закрываем сокет сервера
    	return 0;
    }
    //функция создания и связывания сокета. реализация
    int sock(const char *port, const char *transport, int qlen)
    {
    	struct protoent *ppe;        
    	struct sockaddr_in sin;
    	int s, type;
    	//обнуляем структуру адреса
    	memset(&sin, 0, sizeof(sin)); // @ntdll.dll
    	//указываем тип адреса - IPv4, для IPv6 необходимо указать AF_INET6
    	sin.sin_family = AF_INET;
    	//указываем, в качестве адреса, шаблон INADDR_ANY - все сетевые интерфейсы
    	sin.sin_addr.s_addr = INADDR_ANY;
    	//задаем порт
    	sin.sin_port = htons((unsigned short)atoi(port));
    	//преобразовываем имя транспортного протокола в номер протокола
    	if((ppe = getprotobyname(transport)) == 0)
    	{
    		cprintf("Ошибка преобразования имени транспортного протокола: %s\n", cstrerror(errn));    //в случае неудачи выводим сообщение ошибки
    		return -1;        
    	}
    	//используем имя протокола для определения типа сокета     
    	if(lstrcmp(transport, "udp") == 0)
    		type = SOCK_DGRAM;
    	else
    		type = SOCK_STREAM;    
    	//создаем сокет
    	s = socket(PF_INET, type, ppe->p_proto);
    	if(s < 0)
    	{
    		cprintf("Ошибка создания сокета: %s\n", cstrerror(errn));    //в случае неудачи выводим сообщение ошибки
    		return -1;
    	}
    	//привязка сокета с проверкой результата
    	if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    	{
    		cprintf("Ошибка связывания сокета: %s\n", cstrerror(errn));    //в случае неудачи выводим сообщение ошибки
    		return -1;
    	}
    	//запуск прослушивания с проверкой результата
    	if(type == SOCK_STREAM && listen(s, qlen) <0)
    	{
    		cprintf("Ошибка прослушивания сокета: %s\n", cstrerror(errn));    //в случае неудачи выводим сообщение ошибки
    		return -1;
    	}
    	return s;    //возвращаем дескриптор сокета
    }
    
    
    по поводу комментов, на будущее, не стоит писать например так:
    Code:
    i+=2; // тут увеличиваем счетчик на 2 единицы
     
    #7 sn0w, 19 Feb 2010
    Last edited: 19 Feb 2010
  8. al072

    al072 New Member

    Joined:
    25 May 2008
    Messages:
    20
    Likes Received:
    0
    Reputations:
    0
    Подправил код, подправил заголовочные файлы!(в посте тоже код обновил) всеравно выдает две ошибки, не пойму почему не компилиться:

    LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup

    LNK1120: 1 unresolved externals

    Еще вызывает подозрение вот эта строчка кода : extern errno;

    она в самом начале почти! я ее закоментил, если откоментировать вылазят совсем другие ошибки! Если ты добился того, что все компилиться без проблем, и если не трудно может посмотришь еще раз на код в посте, что-то наверняка я упускаю, но не пойму где?