跨平台开发连载(4_网络通讯类socket)

跨平台网络通讯要注意的地方:(以bsd unix与winsock2为例)

1.      套接口数据类型和错误数值
为了保持与 BSD 的兼容性,应用程序可以加入以下一行代码:
#define INVALID_SOCKET -1
例如:
  BDS 风格
  m_hSocket=socket(…);
  if(m_hSocket=-1)   /* or m_hSocket<0 */
                 {…}
  Windows风格:
  m_hSocket=socket(…);
  if(m_hSocket=INVALID_SOCKET)
                 {…}
2.       select() 函数和FD_*宏
常用FD_*宏来防止错误。
 
3.       错误代码-errno,h_errno,WSAGetLastError()
为了保持与 BSD 的兼容性,应用程序可以加入以下一行代码:
#define WSAGetLastError() errno
例如:
  BSD风格:
  retcode=recv(…);
  if(retcode=-1 && errno=EWOULDBLOCK)
  {…}
  Windows风格:
  retcode=recv(…);
  if(retcode=-1 && WSAGetLastError ()=EWOULDBLOCK)
  {…}
 
4        重命名的函数
#define closesocket(a) close(a)
#define ioctlsocket ioctl
 
5         阻塞
windows虽然支持阻塞,但常用的是非阻塞,而bsd socket默认是阻塞的。
 
6         头文件与库
window下只需加载头文件winsock2.h, 但在链接时要加载依赖库:ws2_32.lib; linux下网络通讯模块是包含在基本的系统库里了,只需根据调用函数包含不同的头文件即可了。
 
下面是一个在linux与windows下都能运行的跨平台网络程序范例:
/**********************************************************
* socket_test.cpp     for test socket on windows and linux
* Copyright (C) |2006-11-9| by denny <[email protected]>
*********************************************************
*/

#include 
< stdio.h >
#include 
< string .h >
#ifndef WIN32
#include 
< sys / socket.h >
#include 
< unistd.h >
#include 
< netinet / in .h >
#include 
< arpa / inet.h >
#include 
< pthread.h >
#define   closesocket(a)  close(a)
#else
#include 
< winsock2.h >
#endif

#define   MAXBUF  512
#define   PORT 2222

typedef 
void *  ( * tc_thread_func)( void * );

void  rcv();                 /*后台接收消息的函数 */
void  snd();                 /*发送消息的函数*/

/*简介:该程序是一个跨平台的一个简单的基于UDP协议聊天工具
  功能:主线程:发送消息
            子线程:接收消息
  作者:wjfree
  使用:运行后发送消息:IP +空格+ Message
  编译:linux 下:gcc ./chatlin.c -lpthread -o chat
          win下:在lcc下添加工程,编译
*/

int  main ()
{
#ifdef WIN32
        WSADATA         wsaData;
        WORD wVersionRequested 
= MAKEWORD( 22 );
        
int err = WSAStartup( wVersionRequested, &wsaData );
        HANDLE      hThread;
        DWORD       dwThreadId;
        hThread
= CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)rcv,NULL,0,&dwThreadId);
        snd();
        WSACleanup();
#else
        pthread_t id;
        
int ret;
        ret 
= pthread_create(&id,NULL,(tc_thread_func)rcv,NULL);        /*创建一个线程*/
        snd();
#endif
        
return 0;
}


/*函数:snd()
  功能:用scanf()函数接收ip地址和消息内容,发到对应的IP上
  作者:wjfree
*/

void  snd()
{

    
struct     sockaddr_in name;
    
int        sock;
    name.sin_family 
= PF_INET;
    name.sin_port 
= htons(PORT);
    sock 
= socket(PF_INET, SOCK_DGRAM,0);
    
if (sock < 0)
    
{
            printf(
"make socket error ");
            
return;
    }

    
while(1)
    
{
        
char bufloc[MAXBUF];
        
char ipaddr[17];
        scanf(
"%s%s" , ipaddr, bufloc);
        
int i = name.sin_addr.s_addr = inet_addr(ipaddr);
        
if (i == -1)
        
{
            printf(
"IP address format error! ");
        }

        
else
        
{
                
int i = sendto(sock, bufloc, strlen(bufloc), 0, (struct sockaddr *)&name, sizeof(name));
                
if (i < 0)
                        printf(
"Can not send the message to %s ", ipaddr);
        }

    }

   closesocket(sock);
}


/*函数:snd()
  功能:接收消息并显示在终端
  作者:wjfree
*/

void  rcv()
{
    
struct sockaddr_in RecvAddr;
    
struct sockaddr_in SenderAddr;
    
int    sock;
    sock 
= socket(AF_INET, SOCK_DGRAM, 0);
    RecvAddr.sin_family 
= AF_INET;
    RecvAddr.sin_port 
= htons(PORT);
    RecvAddr.sin_addr.s_addr 
= htonl(INADDR_ANY);
    bind(sock, (
struct sockaddr *&RecvAddr, sizeof(RecvAddr));
    printf(
"Receiving datagrams... ");
    
while(1)
    
{
        
int size = sizeof(SenderAddr);
        
char RecvBuf[MAXBUF];
        
int  BufLen = MAXBUF;
        
int i = recvfrom(sock,
            RecvBuf,
            BufLen,
            
0,
            (
struct sockaddr *)&SenderAddr,
            (size_t
*)&size);
        RecvBuf[i] 
= 0;
        printf(
"%s: %s ", inet_ntoa(SenderAddr.sin_addr),RecvBuf);
    }

  closesocket(sock);
}

你可能感兴趣的:(跨平台开发连载(4_网络通讯类socket))