跨平台(Windows+Linux)的Socket通讯程序(一)—底层封装

By | 05月17日
Advertisement

【摘要】编写Socket通讯程序是一个老话题。本文重点介绍Windows平台和Linux平台Socket通讯的不同,采用C++,编制了一个简单的跨平台的Socket通讯库。

一、Socket通讯的基础知识

Socket通讯是两个计算机之间最基本的通讯方法,有TCP和UDP两种协议。关于这两种协议的区别,不少文章已有详述,这里,稍微总结一下:

1.TCP是面向连接的,是“流”式的,意即通讯两端建立了一个“数码流管”,该流无头无尾,接收端保证接收顺序,但不保证包的分割。

2.UDP是面向无连接的,是“包”式的,意即通讯两端自由发送数据包,接收端不保证接收顺序,但保证包的分割与发送端一致。

正是基于上述二者的不同,在编程上,它们的区别如下:对TCP连接,服务器端过程(bind->listen->accept->send/receive)与客户端不相同(connect->send/receive),对UDP连接,二者似乎更对等一些(服务器端仅需要bind)。

二、socket在windows下和linux下的区别

一些文章也已涉及,这里,也是综合一下,并加上自己的理解。

项目 Windows Linux
主要头文件 winsock.h/winsock2.h sys/socket.h fcntl.h errno.h
链接库 ws2_32.dll/lib 连接是使用参数:-lstdc
运行时需要libstdc++.so.5,可在/usr/lib目录中创建一个链接。
初始化及退出 初始化需要调用WSAStartup,退出需调用WSACleanup
关闭Socket closesocket 与文件操作相同close
Socket类型 SOCKET 与文件句柄相同int
错误查看 WSAGetLastError 全局变量errno
设置非阻塞模式 int i=1
ioctlsocket(sockethandle,FIONBIO,&i)
fcntl(ockethandle,F_SETFL, O_NONBLOCK)
send/recv函数最后一个参数 一般设置为0 可以有多种组合:MSG_NOSIGNAL,MSG_DONTWAIT,MSG_WAITALL
send的异常 当连接断开,还发数据的时候,不仅send()的返回值会有反映,而且还会像系统发送一个异常消息,如果不作处理,程序会退 出。为此,send()函数的最后一个参数可以设置MSG_NOSIGNAL,禁止send()函数向系统发送异常消息。
WSA宏 除了可以使用标准的socket函数外,微软自己有许多以WSA开始的函数,作为对标准socket函数的封装(可能微软感觉这些函数更好用一些吧)

三、跨平台的Socket辅助程序

以下给出源代码。

sock_wrap.h代码如下,其中用到了platform.h,定义_WIN32_PLATFROM_和_LINUX_PLATFROM_两个宏。

#ifndef _SOCK_WRAP_H_ #define _SOCK_WRAP_H_  #include "platform.h"    #if defined(_WIN32_PLATFROM_)  #include <winsock2.h>  typedef SOCKET HSocket;  #endif    #if defined(_LINUX_PLATFORM_)  #include <netinet/in.h>  #include <sys/socket.h>  #include <sys/types.h>    typedef int HSocket;  #define SOCKET_ERROR  (-1)  #define INVALID_SOCKET  0  #endif      typedef struct  {      int block;      int sendbuffersize;      int recvbuffersize;      int lingertimeout;      int recvtimeout;      int sendtimeout;  } socketoption_t;    typedef struct  {     int nbytes;     int nresult;  } transresult_t;    int InitializeSocketEnvironment();  void FreeSocketEnvironment();  void GetAddressFrom(sockaddr_in *addr, const char *ip, int port);  void GetIpAddress(char *ip, sockaddr_in *addr);  bool IsValidSocketHandle(HSocket handle);  int GetLastSocketError();    HSocket SocketOpen(int tcpudp);  void SocketClose(HSocket &handle);    int SocketBlock(HSocket hs, bool bblock);  int SocketTimeOut(HSocket hs, int recvtimeout, int sendtimeout, int lingertimeout);    int SocketBind(HSocket hs, sockaddr_in *addr);  HSocket SocketAccept(HSocket hs, sockaddr_in *addr);  int SocketListen(HSocket hs, int maxconn);    void SocketSend(HSocket hs, const char *ptr, int nbytes, transresult_t &rt);  void SocketRecv(HSocket hs, char *ptr, int nbytes, transresult_t &rt);  void SocketTryRecv(HSocket hs, char *ptr, int nbytes, int milliseconds, transresult_t &rt);  void SocketTrySend(HSocket hs, const char *ptr, int nbytes, int milliseconds, transresult_t &rt);    void SocketClearRecvBuffer(HSocket hs);    class CSockWrap  {  public:      CSockWrap(int tcpudp);      ~CSockWrap();      void SetAddress(const char *ip, int port);      void SetAddress(sockaddr_in *addr);      int SetTimeOut(int recvtimeout, int sendtimeout, int lingertimeout);      int SetBufferSize(int recvbuffersize, int sendbuffersize);      int SetBlock(bool bblock);        HSocket  GetHandle () { return m_hSocket;}      void Reopen(bool bForceClose);      void Close();      transresult_t Send(void *ptr, int nbytes);      transresult_t Recv(void *ptr, int nbytes );      transresult_t TrySend(void *ptr, int nbytes, int milliseconds);      transresult_t TryRecv(void *ptr, int nbytes, int  milliseconds );      void ClearRecvBuffer();    protected:      HSocket  m_hSocket;      sockaddr_in m_stAddr;      int m_tcpudp;  };      #endif

sock_wrap.cpp代码如下,其中引用了lightThread.h和spantime.h,它们的代码见“跨平台(Windows+Linux)的线程辅助程序”。

#include "platform.h"   #include <stdio.h>  #include <string.h>  #include <fcntl.h>  #include "lightthread.h"  #include "sock_wrap.h"  #include "TimeSpan.h"    #define INVALIDSOCKHANDLE   INVALID_SOCKET    #if defined(_WIN32_PLATFROM_)  #include <windows.h>  #define ISSOCKHANDLE(x)  (x!=INVALID_SOCKET)  #define BLOCKREADWRITE      0  #define NONBLOCKREADWRITE   0  #define SENDNOSIGNAL        0  #define ETRYAGAIN(x)     (x==WSAEWOULDBLOCK||x==WSAETIMEDOUT)  #define gxsprintf   sprintf_s    #endif      #if defined(_LINUX_PLATFORM_)  #include <stdlib.h>  #include <errno.h>  #include <unistd.h>  #include <sys/socket.h>  #include <netinet/in.h>  #include <arpa/inet.h>  #define ISSOCKHANDLE(x)    (x>0)  #define BLOCKREADWRITE      MSG_WAITALL  #define NONBLOCKREADWRITE   MSG_DONTWAIT  #define SENDNOSIGNAL        MSG_NOSIGNAL  #define ETRYAGAIN(x)        (x==EAGAIN||x==EWOULDBLOCK)  #define gxsprintf           snprintf    #endif      void GetAddressFrom(sockaddr_in *addr, const char *ip, int port)  {      memset(addr, 0, sizeof(sockaddr_in));      addr->sin_family = AF_INET;            /*地址类型为AF_INET*/      if(ip)      {          addr->sin_addr.s_addr = inet_addr(ip);      }      else      {          /*网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,          这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址*/          addr->sin_addr.s_addr = htonl(INADDR_ANY);      }      addr->sin_port = htons(port);   /*端口号*/  }  void GetIpAddress(char *ip, sockaddr_in *addr)  {      unsigned char *p =(unsigned char *)( &(addr->sin_addr));      gxsprintf(ip, 17, "%u.%u.%u.%u", *p,*(p+1), *(p+2), *(p+3) );  }    int GetLastSocketError()  {  #if defined(_WIN32_PLATFROM_)      return WSAGetLastError();  #endif    #if defined(_LINUX_PLATFORM_)      return errno;  #endif  }    bool IsValidSocketHandle(HSocket handle)  {      return ISSOCKHANDLE(handle);  }    void SocketClose(HSocket &handle)  {      if(ISSOCKHANDLE(handle))      {  #if defined(_WIN32_PLATFROM_)          closesocket(handle);  #endif    #if defined(_LINUX_PLATFORM_)          close(handle);  #endif          handle = INVALIDSOCKHANDLE;      }  }    HSocket SocketOpen(int tcpudp)  {      int protocol = 0;      HSocket hs;  #if defined(_WIN32_PLATFROM_)      if(tcpudp== SOCK_STREAM) protocol=IPPROTO_TCP;      else if (tcpudp== SOCK_DGRAM) protocol = IPPROTO_UDP;  #endif      hs = socket(AF_INET, tcpudp, protocol);      return hs;  }  int SocketBind(HSocket hs, sockaddr_in *paddr)  {      return bind(hs, (struct sockaddr *)paddr, sizeof(sockaddr_in));  }  int SocketListen(HSocket hs, int maxconn)  {      return listen(hs,maxconn);  }  HSocket SocketAccept(HSocket hs, sockaddr_in *paddr)  {  #if defined(_WIN32_PLATFROM_)      int cliaddr_len = sizeof(sockaddr_in);  #endif  #if defined(_LINUX_PLATFORM_)      socklen_t cliaddr_len = sizeof(sockaddr_in);  #endif      return accept(hs, (struct sockaddr *)paddr, &cliaddr_len);  }  //  // if timeout occurs, nbytes=-1, nresult=1  // if socket error, nbyte=-1, nresult=-1  // if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1  // otherwise nbytes= the count of bytes sent , nresult=0  void SocketSend(HSocket hs, const char *ptr, int nbytes, transresult_t &rt)  {      rt.nbytes = 0;      rt.nresult = 0;      if(!ptr|| nbytes<1) return;        //Linux: flag can be MSG_DONTWAIT, MSG_WAITALL, 使用MSG_WAITALL的时候, socket 必须是处于阻塞模式下,否则WAITALL不能起作用      rt.nbytes = send(hs, ptr, nbytes, BLOCKREADWRITE|SENDNOSIGNAL);      if(rt.nbytes>0)      {          rt.nresult = (rt.nbytes == nbytes)?0:1;      }      else if(rt.nbytes==0)      {         rt.nresult=-1;      }      else      {          rt.nresult = GetLastSocketError();          rt.nresult = ETRYAGAIN(rt.nresult)? 1:-1;      }  }        // if timeout occurs, nbytes=-1, nresult=1  // if socket error, nbyte=-1, nresult=-1  // if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1  void SocketRecv(HSocket hs, char *ptr, int nbytes, transresult_t &rt)  {      rt.nbytes = 0;      rt.nresult = 0;      if(!ptr|| nbytes<1) return;        rt.nbytes = recv(hs, ptr, nbytes, BLOCKREADWRITE);      if(rt.nbytes>0)      {          return;      }      else if(rt.nbytes==0)      {         rt.nresult=-1;      }      else      {          rt.nresult = GetLastSocketError();          rt.nresult = ETRYAGAIN(rt.nresult)? 1:-1;      }    }  //  nbytes= the count of bytes sent  // if timeout occurs, nresult=1  // if socket error,  nresult=-1,  // if the other side has disconnected in either block mode or nonblock mode, nresult=-2  void SocketTrySend(HSocket hs, const char *ptr, int nbytes, int milliseconds, transresult_t &rt)  {      rt.nbytes = 0;      rt.nresult = 0;      if(!ptr|| nbytes<1) return;          int n;      CMyTimeSpan start;      while(1)      {          n = send(hs, ptr+rt.nbytes, nbytes, NONBLOCKREADWRITE|SENDNOSIGNAL);          if(n>0)          {              rt.nbytes += n;              nbytes -= n;              if(rt.nbytes >= nbytes) {    rt.nresult = 0;  break; }          }          else if( n==0)          {              rt.nresult= -2;              break;          }          else          {              n = GetLastSocketError();              if(ETRYAGAIN(n))              {                  CLightThread::DiscardTimeSlice();              }              else              {                  rt.nresult = -1;                  break;              }          }          if(start.GetSpaninMilliseconds()>milliseconds)  { rt.nresult= 1; break;}      }  }  // if timeout occurs, nbytes=-1, nresult=1  // if socket error, nbyte=-1, nresult=-1  // if the other side has disconnected in either block mode or nonblock mode, nbytes=0, nresult=-1  void SocketTryRecv(HSocket hs, char *ptr, int nbytes, int milliseconds, transresult_t &rt)  {      rt.nbytes = 0;      rt.nresult = 0;      if(!ptr|| nbytes<1) return;        if(milliseconds>2)      {          CMyTimeSpan start;          while(1)          {              rt.nbytes = recv(hs, ptr, nbytes, NONBLOCKREADWRITE);              if(rt.nbytes>0)              {                 break;              }              else if(rt.nbytes==0)              {                  rt.nresult = -1;                  break;              }              else              {                  rt.nresult = GetLastSocketError();                  if( ETRYAGAIN(rt.nresult))                  {                     if(start.GetSpaninMilliseconds()>milliseconds)  { rt.nresult= 1; break;}                     CLightThread::DiscardTimeSlice();                  }                  else                  {                      rt.nresult = -1;                      break;                  }              }            }      }      else      {          SocketRecv(hs, ptr, nbytes, rt);      }  }    void SocketClearRecvBuffer(HSocket hs)  {  #if defined(_WIN32_PLATFROM_)      struct timeval tmOut;      tmOut.tv_sec = 0;      tmOut.tv_usec = 0;      fd_set    fds;      FD_ZERO(&fds);      FD_SET(hs, &fds);      int   nRet = 1;      char tmp[100];      int rt;      while(nRet>0)      {          nRet= select(FD_SETSIZE, &fds, NULL, NULL, &tmOut);          if(nRet>0)          {             nRet = recv(hs, tmp, 100,0);          }      }  #endif    #if defined(_LINUX_PLATFORM_)     char tmp[100];     while(recv(hs, tmp, 100, NONBLOCKREADWRITE)> 0);  #endif  }    int SocketBlock(HSocket hs, bool bblock)  {      unsigned long mode;      if( ISSOCKHANDLE(hs))      {  #if defined(_WIN32_PLATFROM_)          mode = bblock?0:1;          return ioctlsocket(hs,FIONBIO,&mode);  #endif    #if defined(_LINUX_PLATFORM_)          mode = fcntl(hs, F_GETFL, 0);                  //获取文件的flags值。          //设置成阻塞模式      非阻塞模式          return bblock?fcntl(hs,F_SETFL, mode&~O_NONBLOCK): fcntl(hs, F_SETFL, mode | O_NONBLOCK);  #endif      }      return -1;  }    int SocketTimeOut(HSocket hs, int recvtimeout, int sendtimeout, int lingertimeout)   //in milliseconds  {      int rt=-1;      if (ISSOCKHANDLE(hs) )      {          rt=0;  #if defined(_WIN32_PLATFROM_)          if(lingertimeout>-1)          {              struct linger  lin;              lin.l_onoff = lingertimeout;              lin.l_linger = lingertimeout ;              rt = setsockopt(hs,SOL_SOCKET,SO_DONTLINGER,(const char*)&lin,sizeof(linger)) == 0 ? 0:0x1;          }          if(recvtimeout>0 && rt == 0)          {              rt = rt | (setsockopt(hs,SOL_SOCKET,SO_RCVTIMEO,(char *)&recvtimeout,sizeof(int))==0?0:0x2);          }          if(sendtimeout>0 && rt == 0)          {              rt = rt | (setsockopt(hs,SOL_SOCKET, SO_SNDTIMEO, (char *)&sendtimeout,sizeof(int))==0?0:0x4);          }  #endif    #if defined(_LINUX_PLATFORM_)     struct timeval timeout;          if(lingertimeout>-1)          {              struct linger  lin;              lin.l_onoff = lingertimeout>0?1:0;              lin.l_linger = lingertimeout/1000 ;              rt = setsockopt(hs,SOL_SOCKET,SO_LINGER,(const char*)&lin,sizeof(linger)) == 0 ? 0:0x1;          }          if(recvtimeout>0 && rt == 0)          {              timeout.tv_sec = recvtimeout/1000;              timeout.tv_usec = (recvtimeout % 1000)*1000;              rt = rt | (setsockopt(hs,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout))==0?0:0x2);          }          if(sendtimeout>0 && rt == 0)          {              timeout.tv_sec = sendtimeout/1000;              timeout.tv_usec = (sendtimeout % 1000)*1000;              rt = rt | (setsockopt(hs,SOL_SOCKET, SO_SNDTIMEO, &timeout,sizeof(timeout))==0?0:0x4);          }  #endif      }      return rt;  }      int InitializeSocketEnvironment()  {  #if defined(_WIN32_PLATFROM_)      WSADATA  Ws;      //Init Windows Socket      if ( WSAStartup(MAKEWORD(2,2), &Ws) != 0 )      {          return -1;      }  #endif      return 0;  }  void FreeSocketEnvironment()  {  #if defined(_WIN32_PLATFROM_)      WSACleanup();  #endif  }  //==============================================================================================================  //================================================================================================================  CSockWrap::CSockWrap(int tcpudp)  {      memset(&m_stAddr, 0, sizeof(sockaddr_in));      m_tcpudp = tcpudp;      m_hSocket = INVALIDSOCKHANDLE;      Reopen(false);  }      CSockWrap::~CSockWrap()  {      SocketClose(m_hSocket);  }  void CSockWrap::Reopen(bool bForceClose)  {        if (ISSOCKHANDLE(m_hSocket) && bForceClose) SocketClose(m_hSocket);      if (!ISSOCKHANDLE(m_hSocket) )      {          m_hSocket=SocketOpen(m_tcpudp);      }    }  void CSockWrap::SetAddress(const char *ip, int port)  {      GetAddressFrom(&m_stAddr, ip, port);  }  void CSockWrap::SetAddress(sockaddr_in *addr)  {      memcpy(&m_stAddr, addr, sizeof(sockaddr_in));  }    int CSockWrap::SetTimeOut(int recvtimeout, int sendtimeout, int lingertimeout)   //in milliseconds  {    return SocketTimeOut(m_hSocket, recvtimeout, sendtimeout, lingertimeout);  }    int CSockWrap::SetBufferSize(int recvbuffersize, int sendbuffersize)   //in bytes  {      int rt=-1;      if (ISSOCKHANDLE(m_hSocket) )      {  #if defined(_WIN32_PLATFROM_)          if(recvbuffersize>-1)          {              rt = setsockopt( m_hSocket, SOL_SOCKET, SO_RCVBUF, ( const char* )&recvbuffersize, sizeof( int ) );          }          if(sendbuffersize>-1)          {              rt = rt | (setsockopt(m_hSocket,SOL_SOCKET,SO_SNDBUF,(char *)&sendbuffersize,sizeof(int))==0?0:0x2);          }  #endif      }      return rt;  }    int CSockWrap::SetBlock(bool bblock)  {      return SocketBlock(m_hSocket, bblock);  }  transresult_t CSockWrap::Send(void *ptr, int nbytes)  {      transresult_t rt;      SocketSend(m_hSocket, (const char *)ptr, nbytes,rt);      return rt;  }  transresult_t CSockWrap::Recv(void *ptr, int nbytes )  {      transresult_t rt;      SocketRecv(m_hSocket, (char *)ptr, nbytes,rt);      return rt;  }  transresult_t CSockWrap::TrySend(void *ptr, int nbytes, int milliseconds)  {      transresult_t rt;      SocketTrySend(m_hSocket, (const char *)ptr, nbytes,milliseconds, rt);      return rt;  }  transresult_t CSockWrap::TryRecv(void *ptr, int nbytes, int  milliseconds )  {      transresult_t rt;      SocketTryRecv(m_hSocket, (char *)ptr, nbytes,milliseconds, rt);      return rt;  }    void CSockWrap::ClearRecvBuffer()  {      SocketClearRecvBuffer(m_hSocket);  }

上面的辅助程序实际上包含了对一些常用的socket函数的封装和一个类CSockWrap,如果需要自己组建通讯逻辑,可以直接用这些C风格的函数,CSockWrap实际上就是这样一个应用。发送和接收函数的返回值有点复杂,是一个结构体transresult_t,本文的意思是,如果发生接收/发送错误,直接从函数的返回值大致判断下一步的动作。

四、关于Socket通讯过程的一些讨论

1.关于send函数。Socket中Send函数的意思是只要将应用程序的数据发送到网卡中就算成功,将发送端的网线拔掉与将接收端的网线拔掉,Send函数的返回可能不同,因此它的正常返回不能作为接收方是否收到的判断条件。如果需要确保对方收到信息,只能采用应答式,但这样做可能会降低双方的通讯效率。一般情况下,Send不会阻塞,除非网卡的发送缓冲区已经满了(发送端直接掉线)。

2.关于recv函数。Recv是最常用的阻塞函数,但通常情况下,应设置其为非阻塞(windows将整个Socket连接都设为非阻塞,linux可以有两种方式),因为,如果发送方已经掉线,或者还需要干别的事情,让Recv阻塞显然是不合适的。当然,也可以不用Recv,而用非阻塞的Select函数(本文没有涉及Select函数),其实它们的效果是一样的。

3.关于从send和recv函数的返回值来初步判断网络状态,见SocketSend等函数的注释。

4.采用UDP通讯时,数据包的内容不宜过大,所以UDP特别适合于命令的传输(一次的通讯量小,但可能频繁)。

5.SocketClearRecvBuffer函数一般用于TCP连接,当接收方发觉由”丢包“时,作为”对齐“信息包之用。

(想到哪,写到哪,以后再补充)

Similar Posts:

  • VC与linux通过socket通讯

    参考:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html socket编程大家都很熟悉,我在这里就不再罗嗦了.直接切入正题. 该程序分两部分,server端和client端(谁都知道).其中server端采用windows平台,那linux平台当然是client端了. 这里是server端程序: /**********************************/ /* it worked as server under

  • 修改 堆栈大小 普适性方案总结 (跨平台 windows linux 栈设置大小)

    http://www.cnblogs.com/titer1/archive/2012/03/31/2427436.html 栈的大小可以修改的.在应用程序我们经常需要定义大的数组,数组定义成局部变量非静态变量,那么数组就会在栈上分配,当数组超过默认栈的大小时,会引起非常内存访问.那么如何修改系统默认的栈的大小呢. 一般,在Unix-like平台,栈的大小不是由程序自己来控制的而是由环境变量来控制的,所以就不能通过设置编译器(像gcc)的任何编译标志来设置栈的大小: //66上面这种说法,是不是,

  • Linux下socket异步通讯聊天程序

    Linux下socket异步通讯聊天程序(转) original from: http://yangqi.org/linux-socket-asynchronous-im-system/ Posted by yangqi @ 2010年02月17日 [Wed] 22:37 网络课的project 1能用到的资料,程序结构比较清晰,转来学习一下 什么是异步通讯? 就是通讯任意一方可以任意发送消息,有消息来到时会收到系统提示去接收消息. 这里要用到select函数.使用步骤如下: 1.设置一个集合变

  • Linux利用socket实现两台pc之间的数据传输功能,包括windows到linux,TCP/IP实现

    Linux利用socket实现两台pc之间的数据传输功能,包括windows到linux 连接选项 -lWs2_32 代表要用Ws2_32.lib这个库 gcc编译选项,-D 代表定义一个宏,等同于在c语言当中定义 #defind WIN 在windows下,使用socket之前,必须使用WSAStartup初始化socket,程序运行结束以后必须调用WSACleanup释放相关资源 windown下,关闭socket使用closesocket函数 先看一下linux环境下的makefile文件

  • Windows moible 连接GPRS 建立socket 通讯

    对于桌面开发应用建立SOCKET 通讯只要有对应的端口,及一个网络通道即可以建立连接.而对于windows mobile 也是一样,前提是一定要有一个通讯通道,然后指定对应端口,近来有朋友问起为什么windows mobile 开发程序无法建立socket 连接,是不是移动屏蔽了端口,其实并不是如此,只是建立通讯的基础上少了一步而已.对于移动设备而言,网络通讯并不是一直连接着的,在用到网络资源的时候打开无线连接然后在通讯,建立无线通讯的方式也很多,比如说cmwap,cmnet,包括现在3G.使用

  • Windows Socket聊天程序说明报告

    源文件: 主程序头文件:winsocket main.h http://blog.csdn.net/huyoo/archive/2004/12/02/201380.aspx 对话框资源文件和ID定义:winsocket rc http://blog.csdn.net/huyoo/archive/2004/12/02/201379.aspx 主程序主文件:winsocket main.cpp http://blog.csdn.net/huyoo/archive/2004/12/02/201378.

  • Linux,Windows下执行java应用程序的Batch命令

    Linux下,Windows下执行java应用程序的Batch命令 Linuxで: ServerHome=/usr/local/hq/MeiShiKouServer PRE_CLASSPATH=./bin:$(ls $ServerHome/lib/*.*|tr " " :) MAIN_CLASS= test.GeneralInfoMain java -cp $PRE_CLASSPATH -Djava.security.policy=policy.all -DSystemConfig=$

  • 在CB中用socket api来写网络通讯程序

    关键字:socket,api,网络通讯程序,TCP,UDP 作者:kingcaiyao 更新:2003-09-10 浏览:14250 本文转自csdn,作者:kingcaiyao 原标题:在C++ Builder中用socket api来写网络通讯程序(同时支持TCP和UDP协议) 原文: http://www.csdn.net/develop/read_article.asp?id=19883 在7月4日看完sockcomp.pas后,我决定用socket api来写一个客户端和服务器并且同时

  • Linux多线程socket程序异常退出-断开的管道

    linux程序多线程socket程序出现断开的管道 问题描述: socket在侦听情况下,接受一个外部的socket,但是还没有处理.之后该socket已经断开,但是程序却继续处理这个socket,此时会导致程序处理一个断开的socket,程序退出. 处理方法: 在程序中添加: struct sigaction action; //信号处理结构体 action.sa_handler = function; //产生信号时的处理函数 sigemptyset(&action.sa_mask); ac

  • windows下C++和C#间socket通讯乱码问题解决方案

    初学C++和网络编程 最近在做个C++和C#间socket通讯的程序,本来对C++就不熟悉,对C++的网络编程就更不熟悉了,结果被传输中文时乱码的问题搞了好几天 参考了以下文章终于解决: http://www.80edu.com/html/it/net/jishu/9346.html http://www.cppblog.com/sunraiing9/archive/2007/03/21/20281.html 还有好几篇比较久之前看到的,内容跟上面的差不多 具体解决方案如下: C++端: //b

Tags: