zoukankan      html  css  js  c++  java
  • 转:socket编程在windows和linux下的区别

    如无其它说明,本文所指Linux均表示2.6内核Linux,GCC编译器,Windows均表示Windows XP系统,Visual Studio 2005 sp1编译环境。


    下面大概分几个方面进行罗列:

    Linux要包含

    [cpp] 
    #include <sys/socket.h>   
    #include <netinet/in.h>   
    #include <netdb.h>   
    #include <arpa/inet.h>  
    等头文件,而windows下则是包含
    [cpp] 
    #include <winsock.h>  



    Linux中socket为整形,Windows中为一个SOCKET。
    Linux中关闭socket为close,Windows中为closesocket。
    Linux中有变量socklen_t,Windows中直接为int。
    因为linux中的socket与普通的fd一样,所以可以在TCP的socket中,发送与接收数据时,直接使用read和write。而windows只能使用recv和send。
    设置socet选项,比如设置socket为非阻塞的。Linux下为

    [cpp] 
    flag = fcntl (fd, F_GETFL);  
    fcntl (fd, F_SETFL, flag | O_NONBLOCK);  
    ,Windows下为
    [cpp] 
    flag = 1;  
    ioctlsocket (fd, FIONBIO, (unsigned long *) &flag);  

    当非阻塞socket的TCP连接正在进行时,Linux的错误号为EINPROGRESS,Windows的错误号为WSAEWOULDBLOCK。


    file
    Linux下面,文件换行是" ",而windows下面是" "。
    Linux下面,目录分隔符是"/",而windows下面是""。
    Linux与Windows下面,均可以使用stat调用来查询文件信息。但是,Linux只支持2G大小,而Windows只支持4G大小。为了支持更大的文件查询,可以在Linux环境下加


    _FILE_OFFSET_BITS=64定义,在Windows下面使用_stat64调用,入参为struct __stat64。
    Linux中可根据stat的st_mode判断文件类型,有S_ISREG、S_ISDIR等宏。Windows中没有,需要自己定义相应的宏,如


    [cpp] 
    #define S_ISREG(m) (((m) & 0170000) == (0100000))   
    #define S_ISDIR(m) (((m) & 0170000) == (0040000))  
    Linux中删除文件是unlink,Windows中为DeleteFile。

    time

    Linux中,time_t结构是长整形。而windows中,time_t结构是64位的整形。如果要在windows始time_t为32位无符号整形,可以加宏定义,_USE_32BIT_TIME_T。
    Linux中,sleep的单位为秒。Windows中,Sleep的单位为毫秒。即,Linux下sleep (1),在Windows环境下则需要Sleep (1000)。
    Windows中的timecmp宏,不支持大于等于或者小于等于。
    Windows中没有struct timeval结构的加减宏可以使用,需要手动定义:


    [cpp] 
    #define MICROSECONDS (1000 * 1000)   
      
    #define timeradd(t1, t2, t3) do {                                                             
      (t3)->tv_sec = (t1)->tv_sec + (t2)->tv_sec;                                                
      (t3)->tv_usec = (t1)->tv_usec + (t2)->tv_usec % MICROSECONDS;                              
      if ((t1)->tv_usec + (t2)->tv_usec > MICROSECONDS) (t3)->tv_sec ++;                        
    } while (0)  
      
    #define timersub(t1, t2, t3) do {                                                             
      (t3)->tv_sec = (t1)->tv_sec - (t2)->tv_sec;                                                
      (t3)->tv_usec = (t1)->tv_usec - (t2)->tv_usec;                                            
      if ((t1)->tv_usec - (t2)->tv_usec < 0) (t3)->tv_usec --, (t3)->tv_usec += MICROSECONDS;    
    } while (0)  


    调用进程

    Linux下可以直接使用system来调用外部程序。Windows最好使用WinExec,因为WinExec可以支持是打开还是隐藏程序窗口。用WinExec的第二个入参指明,如

    SW_SHOW/SW_HIDE。

    杂项

    Linux为srandom和random函数,Windows为srand和rand函数。
    Linux为snprintf,Windows为_snprintf。
    同理,Linux中的strcasecmp,Windows为_stricmp。


    错误处理

    Linux下面,通常使用全局变量errno来表示函数执行的错误号。Windows下要使用GetLastError ()调用来取得。


    Linux环境下仅有的
    这些函数或者宏,Windows中完全没有,需要用户手动实现。
    atoll

    [cpp] 
    long long  
    atoll (const char *p)  
    {  
      int minus = 0;  
      long long value = 0;  
      if (*p == '-')  
        {  
          minus ++;  
          p ++;  
        }  
      while (*p >= '0' && *p <= '9')  
        {  
          value *= 10;  
          value += *p - '0';  
          p ++;  
        }  
      return minus ? 0 - value : value;  
    }  
    gettimeofday


    [cpp] 
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)   
    #define EPOCHFILETIME  11644473600000000Ui64   
    #else   
    #define EPOCHFILETIME  11644473600000000ULL   
    #endif   
      
    struct timezone  
    {  
      int tz_minuteswest;  
      int tz_dsttime;  
    };  
      
    int  
    gettimeofday (struct timeval *tv, struct timezone *tz)  
    {  
      FILETIME ft;  
      LARGE_INTEGER li;  
      __int64 t;  
      static int tzflag;  
      
      if (tv)  
        {  
          GetSystemTimeAsFileTime (&ft);  
          li.LowPart = ft.dwLowDateTime;  
          li.HighPart = ft.dwHighDateTime;  
          t = li.QuadPart;      /* In 100-nanosecond intervals */  
          t -= EPOCHFILETIME;   /* Offset to the Epoch time */  
          t /= 10;          /* In microseconds */  
          tv->tv_sec = (long) (t / 1000000);  
          tv->tv_usec = (long) (t % 1000000);  
        }  
      
      if (tz)  
        {  
          if (!tzflag)  
        {  
          _tzset ();  
          tzflag++;  
        }  
          tz->tz_minuteswest = _timezone / 60;  
          tz->tz_dsttime = _daylight;  
        }  
      
      return 0;  
    }  

    编译相关
    当前函数,Linux用__FUNCTION__表示,Windows用__func__表示。
    --------------------------------------------------------------------------------
    Socket 编程 windows到Linux代码移植遇到的问题
    1)头文件  
    windows下winsock.h/winsock2.h  
    linux下sys/socket.h  
    错误处理:errno.h  


    2)初始化  
    windows下需要用WSAStartup  
    linux下不需要  


    3)关闭socket  
    windows下closesocket(...)  
    linux下close(...)  

    4)类型  
    windows下SOCKET  
    linux下int  
    如我用到的一些宏:  
    #ifdef WIN32  
    typedef int socklen_t;  
    typedef int ssize_t;  
    #endif  

    #ifdef __LINUX__  
    typedef int SOCKET;  
    typedef unsigned char BYTE;  
    typedef unsigned long DWORD;  
    #define FALSE 0  
    #define SOCKET_ERROR (-1)  
    #endif  


    5)获取错误码  
    windows下getlasterror()/WSAGetLastError()  
    linux下errno变量  


    6)设置非阻塞  
    windows下ioctlsocket()  
    linux下fcntl() <fcntl.h>  

    7)send函数最后一个参数  
    windows下一般设置为0  
    linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可 能会导致程序退出。  


    8)毫秒级时间获取  
    windows下GetTickCount()  
    linux下gettimeofday()  


    3、多线程  
    多线程: (win)process.h --〉(linux)pthread.h  
    _beginthread --> pthread_create  
    _endthread --> pthread_exit
    -----------------------------------------------------------------
    windows与linux平台使用的socket均继承自Berkeley socket(rfc3493),他们都支持select I/O模型,均支持使用getaddrinfo与getnameinfo实现协议无关编程。但存在细微差别,

    主要有:

    头文件及类库。windows使用winsock2.h(需要在windows.h前包含),并要链接库ws2_32.lib;linux使用netinet/in.h, netdb.h等。
    windows下在使用socket之前与之后要分别使用WSAStartup与WSAClean。
    关闭socket,windows使用closesocket,linux使用close。
    send*与recv*函数参数之socket长度的类型,windows为int,linux为socklen_t,可预编译指令中处理这一差异,当平台为windows时#define socklen_t unsigned int。
    select函数第一个参数,windows忽略该参数,linux下该参数表示集合中socket的上限值,一般设为sockfd(需select的socket) + 1。
    windows下socket函数返回值类型为SOCKET(unsigned int),其中发生错误时返回INVALID_SOCKET(0),linux下socket函数返回值类型int, 发生错误时返回-1。
    另外,如果绑定本机回环地址,windows下sendto函数可以通过,linux下sendto回报错:errno=22, Invalid arguement。一般情况下均绑定通配地址。

    转自:http://www.cnblogs.com/dyllove98/archive/2013/06/23/3151162.html

  • 相关阅读:
    小波变换的引入,通俗易懂
    Leetcode 437. Path Sum III
    Leetcode 113. Path Sum II
    Leetcode 112 Path Sum
    Leetcode 520 Detect Capital
    Leetcode 443 String Compression
    Leetcode 38 Count and Say
    python中的生成器(generator)总结
    python的random模块及加权随机算法的python实现
    leetcode 24. Swap Nodes in Pairs(链表)
  • 原文地址:https://www.cnblogs.com/youxin/p/3965966.html
Copyright © 2011-2022 走看看