??xml version="1.0" encoding="utf-8" standalone="yes"?>久久综合五月丁香久久激情,国产精品美女久久久m,国产精品日韩深夜福利久久http://www.shnenglu.com/keigoliye/category/11701.html一切都是纸老虎zh-cnMon, 13 Sep 2010 20:55:54 GMTMon, 13 Sep 2010 20:55:54 GMT60c & c++ pluginshttp://www.shnenglu.com/keigoliye/archive/2010/09/13/126511.html暗夜教父暗夜教父Mon, 13 Sep 2010 08:45:00 GMThttp://www.shnenglu.com/keigoliye/archive/2010/09/13/126511.htmlhttp://www.shnenglu.com/keigoliye/comments/126511.htmlhttp://www.shnenglu.com/keigoliye/archive/2010/09/13/126511.html#Feedback0http://www.shnenglu.com/keigoliye/comments/commentRss/126511.htmlhttp://www.shnenglu.com/keigoliye/services/trackbacks/126511.html

在AX3+SP3中有一个工具Code ProfilerQ近来发现是非常好用的工P可以查代码运行的轨迹Q以?qing)代码运行的旉Q对于跟t代码是非常有效的?/p>


C++代码度量工具-cccc
软g度量多个指标依赖于代码行l计Q如每千行代码发?/span>bug{,所以代码行是一个基数据。CCCC度量数据可结合测试风险完善测试计划?br>

CodeStatistics
一个小的命令行工具。我主要用它来做两g事情Q一者是代码l计功能Q另一者是删除I白行功能。在某此时候,我觉得对于整理代码和了解代码情况q是有一定的帮助作用的。明天我?x)将代码的行l束W格式加上的Q当Ӟq有分析代码元素Q如有多个函数Q多个c,也在我确定要d的功能之内。当Ӟ能整理代码就更棒了?br>

静态代码分析工具Cppcheck
Cppcheck是一Ƒּ?/span>c++静态代码分析工?/span>,在检源码时可根据规则就能挖掘出疑似~陷, 帮开源项目发现的bug?/span>:

http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Found_bugs

功能比较强大,使用很简?br>



 



暗夜教父 2010-09-13 16:45 发表评论
]]>
Uc语言实现的IOCP服务?/title><link>http://www.shnenglu.com/keigoliye/archive/2010/02/24/108341.html</link><dc:creator>暗夜教父</dc:creator><author>暗夜教父</author><pubDate>Wed, 24 Feb 2010 05:34:00 GMT</pubDate><guid>http://www.shnenglu.com/keigoliye/archive/2010/02/24/108341.html</guid><wfw:comment>http://www.shnenglu.com/keigoliye/comments/108341.html</wfw:comment><comments>http://www.shnenglu.com/keigoliye/archive/2010/02/24/108341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/keigoliye/comments/commentRss/108341.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/keigoliye/services/trackbacks/108341.html</trackback:ping><description><![CDATA[<span style="font-family: Arial; font-size: 14px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; ">#include   <winsock2.h>   <br style="line-height: normal; ">//#include   <windows.h>   <br style="line-height: normal; ">#include   <stdio.h>   <br style="line-height: normal; "><br style="line-height: normal; ">#define   PORT   5150   <br style="line-height: normal; ">#define   DATA_BUFSIZE   8192   <br style="line-height: normal; ">    <br style="line-height: normal; ">typedef   struct   <br style="line-height: normal; ">{   <br style="line-height: normal; ">        OVERLAPPED   Overlapped;   <br style="line-height: normal; ">        WSABUF   DataBuf;   <br style="line-height: normal; ">        CHAR   Buffer[DATA_BUFSIZE];   <br style="line-height: normal; ">        DWORD   BytesSEND;   <br style="line-height: normal; ">        DWORD   BytesRECV;   <br style="line-height: normal; ">}   PER_IO_OPERATION_DATA,   *   LPPER_IO_OPERATION_DATA;   <br style="line-height: normal; ">    <br style="line-height: normal; ">    <br style="line-height: normal; ">typedef   struct     <br style="line-height: normal; ">{   <br style="line-height: normal; ">        SOCKET   Socket;   <br style="line-height: normal; ">}   PER_HANDLE_DATA,   *   LPPER_HANDLE_DATA;   <br style="line-height: normal; ">    <br style="line-height: normal; ">    <br style="line-height: normal; ">DWORD   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID);   <br style="line-height: normal; ">    <br style="line-height: normal; ">int main(void)   <br style="line-height: normal; ">{   <br style="line-height: normal; ">        SOCKADDR_IN   InternetAddr;   <br style="line-height: normal; ">        SOCKET   Listen;   <br style="line-height: normal; ">        SOCKET   Accept;   <br style="line-height: normal; ">        HANDLE   CompletionPort;   <br style="line-height: normal; ">        SYSTEM_INFO   SystemInfo;   <br style="line-height: normal; ">        LPPER_HANDLE_DATA   PerHandleData;   <br style="line-height: normal; ">        LPPER_IO_OPERATION_DATA   PerIoData;   <br style="line-height: normal; ">        int   i;   <br style="line-height: normal; ">        DWORD   RecvBytes;   <br style="line-height: normal; ">        DWORD   Flags;   <br style="line-height: normal; ">        DWORD   ThreadID;   <br style="line-height: normal; ">        WSADATA   wsaData;   <br style="line-height: normal; ">        DWORD   Ret;   <br style="line-height: normal; ">    <br style="line-height: normal; ">        if   ((Ret   =   WSAStartup(0x0202,   &wsaData))   !=   0)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              printf("WSAStartupp|了,错误信息如下:   %d\n",   Ret);   <br style="line-height: normal; ">              return;   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">    <br style="line-height: normal; ">        // 讄一个I/O完成端口.   <br style="line-height: normal; ">    <br style="line-height: normal; ">        if   ((CompletionPort   =   CreateIoCompletionPort(INVALID_HANDLE_VALUE,   NULL,   0,   0))   ==   NULL)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              printf(   "CreateIoCompletionPort p|了,错误信息如下:   %d\n",   GetLastError());   <br style="line-height: normal; ">              return;   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">    <br style="line-height: normal; ">        // 试pȝ中有多少cpu处理?nbsp;<br style="line-height: normal; ">    <br style="line-height: normal; ">        GetSystemInfo(&SystemInfo);   <br style="line-height: normal; ">    <br style="line-height: normal; ">        //   Zpȝ可用的处理器创徏工作U程Qؓ(f)每个处理器创个线E?nbsp;  <br style="line-height: normal; ">    <br style="line-height: normal; ">        for(i   =   0;   i   <   SystemInfo.dwNumberOfProcessors   *   2;   i++)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              HANDLE   ThreadHandle;   <br style="line-height: normal; ">    <br style="line-height: normal; ">              // 创徏一个服务端U程q且传递一个完成端口给q个U程.   <br style="line-height: normal; ">    <br style="line-height: normal; ">              if   ((ThreadHandle   =   CreateThread(NULL,   0,   ServerWorkerThread,   CompletionPort,   <br style="line-height: normal; ">                    0,   &ThreadID))   ==   NULL)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("CreateThread()发生了如下错误:(x) %d\n",   GetLastError());   <br style="line-height: normal; ">                    return;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">              else <br style="line-height: normal; ">              {printf("创徏了一个完成端?\n");<br style="line-height: normal; ">              }<br style="line-height: normal; ">              //   关闭 thread句柄 <br style="line-height: normal; ">              CloseHandle(ThreadHandle);   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">    <br style="line-height: normal; ">        //   创徏一个监听套接字 <br style="line-height: normal; ">    <br style="line-height: normal; ">        if   ((Listen   =WSASocket(AF_INET,   SOCK_STREAM,   0,   NULL,0,WSA_FLAG_OVERLAPPED))   ==   INVALID_SOCKET)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              printf("WSASocket() 发生了如下错误:(x) %d\n",   WSAGetLastError());   <br style="line-height: normal; ">              return;   <br style="line-height: normal; ">        }<br style="line-height: normal; ">        else     <br style="line-height: normal; ">        {printf("创徏监听套接字成功\n");}<br style="line-height: normal; ">        InternetAddr.sin_family   =   AF_INET;   <br style="line-height: normal; ">        InternetAddr.sin_addr.s_addr   =   htonl(INADDR_ANY);   <br style="line-height: normal; ">        InternetAddr.sin_port   =   htons(PORT);   <br style="line-height: normal; ">    <br style="line-height: normal; ">        if   (bind(Listen,   (PSOCKADDR)   &InternetAddr,   sizeof(InternetAddr))   ==   SOCKET_ERROR)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              printf("bind()端口或IP时发生了如下错误Q?%d\n",   WSAGetLastError());   <br style="line-height: normal; ">              return;   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">        else<br style="line-height: normal; ">        {printf("l定端口%d成功\n",PORT);} <br style="line-height: normal; ">        // 准备socket 用来监听   <br style="line-height: normal; ">    <br style="line-height: normal; ">        if   (listen(Listen,   5)   ==   SOCKET_ERROR)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              printf("listen() 发生了如下错?nbsp;  %d\n",   WSAGetLastError());   <br style="line-height: normal; ">              return;   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">         else<br style="line-height: normal; ">        {printf("预处理成功,开始在端口 %d 处监?..\n",PORT);} <br style="line-height: normal; ">        //接受q接q且交给完成端口处理 <br style="line-height: normal; ">    <br style="line-height: normal; ">        while(TRUE)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">              if   ((Accept   =   WSAAccept(Listen,   NULL,   NULL,   NULL,   0))   ==   SOCKET_ERROR)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("WSAAccept()   发生了如下错误:(x)   %d\n",   WSAGetLastError());   <br style="line-height: normal; ">                    return;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    <br style="line-height: normal; ">              // 创徏一个套接字信息l构体去联系hsocket   <br style="line-height: normal; ">              if   ((PerHandleData   =   (LPPER_HANDLE_DATA)   GlobalAlloc(GPTR,     <br style="line-height: normal; ">                    sizeof(PER_HANDLE_DATA)))   ==   NULL)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("GlobalAlloc()   发生了如下错误:(x)   %d\n",   GetLastError());   <br style="line-height: normal; ">                    return;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    <br style="line-height: normal; ">              // 接受到的套接字与原始的完成端口联系h.   <br style="line-height: normal; ">    <br style="line-height: normal; ">              printf("L(fng)?nbsp;  %d   的socketq接上了\n",   Accept);   <br style="line-height: normal; ">              PerHandleData->Socket   =   Accept;   <br style="line-height: normal; ">    <br style="line-height: normal; ">              if   (CreateIoCompletionPort((HANDLE)   Accept,   CompletionPort,   (DWORD)   PerHandleData,   <br style="line-height: normal; ">                    0)   ==   NULL)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("CreateIoCompletionPort   发生了如下错误:(x)   %d\n",   GetLastError());   <br style="line-height: normal; ">                    return;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    <br style="line-height: normal; ">              //   创徏每一个I/O 套接字信息结构体d下面被调用的 to   associate   with   the     <br style="line-height: normal; ">              //   WSARecv q接.   <br style="line-height: normal; ">    <br style="line-height: normal; ">              if   ((PerIoData   =   (LPPER_IO_OPERATION_DATA)   GlobalAlloc(GPTR,                     sizeof(PER_IO_OPERATION_DATA)))   ==   NULL)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("GlobalAlloc() 发生了如下错误:(x) %d\n",   GetLastError());   <br style="line-height: normal; ">                    return;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">              else{printf("接收了一个连接\n");} <br style="line-height: normal; ">              ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   <br style="line-height: normal; ">              PerIoData->BytesSEND   =   0;   <br style="line-height: normal; ">              PerIoData->BytesRECV   =   0;   <br style="line-height: normal; ">              PerIoData->DataBuf.len   =   DATA_BUFSIZE;   <br style="line-height: normal; ">              PerIoData->DataBuf.buf   =   PerIoData->Buffer;   <br style="line-height: normal; ">    <br style="line-height: normal; ">              Flags   =   0;   <br style="line-height: normal; ">              if   (WSARecv(Accept,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,   <br style="line-height: normal; ">                    &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   <br style="line-height: normal; ">                    {   <br style="line-height: normal; ">                          printf("WSARecv() 发生了如下错误:(x) %d\n",   WSAGetLastError());   <br style="line-height: normal; ">                          return;   <br style="line-height: normal; ">                    }   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">}   <br style="line-height: normal; ">    <br style="line-height: normal; ">DWORD   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID)   <br style="line-height: normal; ">{   <br style="line-height: normal; ">        HANDLE   CompletionPort   =   (HANDLE)   CompletionPortID;   <br style="line-height: normal; ">        DWORD   BytesTransferred;   <br style="line-height: normal; ">        LPOVERLAPPED   Overlapped;   <br style="line-height: normal; ">        LPPER_HANDLE_DATA   PerHandleData;   <br style="line-height: normal; ">        LPPER_IO_OPERATION_DATA   PerIoData;   <br style="line-height: normal; ">        DWORD   SendBytes,   RecvBytes;   <br style="line-height: normal; ">        DWORD   Flags;   <br style="line-height: normal; ">          <br style="line-height: normal; ">        while(TRUE)   <br style="line-height: normal; ">        {   <br style="line-height: normal; ">    <br style="line-height: normal; ">              if   (GetQueuedCompletionStatus(CompletionPort,   &BytesTransferred,   <br style="line-height: normal; ">                    (LPDWORD)&PerHandleData,   (LPOVERLAPPED   *)   &PerIoData,   INFINITE)   ==   0)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("GetQueuedCompletionStatus   发生了如下错误:(x) %d\n",   GetLastError());   <br style="line-height: normal; ">                    return   0;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    <br style="line-height: normal; ">              //首先查一下去套接字看是否在上发生了错误ƈ且如果发生了错误关闭套?br style="line-height: normal; ">              //字ƈ且清除与套接字连接的 SOCKET_INFORMATIONl构信息?nbsp;<br style="line-height: normal; ">              if   (BytesTransferred   ==   0)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    printf("正在关闭socket   %d\n",   PerHandleData->Socket);   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    if   (closesocket(PerHandleData->Socket)   ==   SOCKET_ERROR)   <br style="line-height: normal; ">                    {   <br style="line-height: normal; ">                          printf("closesocket()   发生了如下错误:(x) %d\n",   WSAGetLastError());   <br style="line-height: normal; ">                          return   0;   <br style="line-height: normal; ">                    }   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    GlobalFree(PerHandleData);   <br style="line-height: normal; ">                    GlobalFree(PerIoData);   <br style="line-height: normal; ">                    continue;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    //查如?BytesRECV字段{于0Q这意味着一?WSARecv调用刚刚完成了所以从完成的WSARecv()调用?br style="line-height: normal; ">    //用BytesTransferred值更?BytesRECV字段 <br style="line-height: normal; ">              if   (PerIoData->BytesRECV   ==   0)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    PerIoData->BytesRECV   =   BytesTransferred;   <br style="line-height: normal; ">                    PerIoData->BytesSEND   =   0;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">              else   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    PerIoData->BytesSEND   +=   BytesTransferred;   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">    <br style="line-height: normal; ">              if   (PerIoData->BytesRECV   >   PerIoData->BytesSEND)   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">    //发布另外一?WSASend()h<br style="line-height: normal; ">    //既然WSASend()不是 gauranteedd送所有字节的h<br style="line-height: normal; ">    //l箋调用 WSASend()发送直到所有收到的字节被发?nbsp;<br style="line-height: normal; ">                    <br style="line-height: normal; ">                    ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    PerIoData->DataBuf.buf   =   PerIoData->Buffer   +   PerIoData->BytesSEND;   <br style="line-height: normal; ">                    PerIoData->DataBuf.len   =   PerIoData->BytesRECV   -   PerIoData->BytesSEND;   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    if   (WSASend(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &SendBytes,   0,   <br style="line-height: normal; ">                          &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   <br style="line-height: normal; ">                    {   <br style="line-height: normal; ">                          if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   <br style="line-height: normal; ">                          {   <br style="line-height: normal; ">                                printf("WSASend() 发生了如下错误:(x)   %d\n",   WSAGetLastError());   <br style="line-height: normal; ">                                return   0;   <br style="line-height: normal; ">                          }   <br style="line-height: normal; ">                    }   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">              else   <br style="line-height: normal; ">              {   <br style="line-height: normal; ">                    PerIoData->BytesRECV   =   0;   <br style="line-height: normal; ">    //现在没有更多的字节发送过ȝ来post另外一个WSARecv()h <br style="line-height: normal; ">                    <br style="line-height: normal; ">                    Flags   =   0;   <br style="line-height: normal; ">                    ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    PerIoData->DataBuf.len   =   DATA_BUFSIZE;   <br style="line-height: normal; ">                    PerIoData->DataBuf.buf   =   PerIoData->Buffer;   <br style="line-height: normal; ">    <br style="line-height: normal; ">                    if   (WSARecv(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,   <br style="line-height: normal; ">                          &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   <br style="line-height: normal; ">                    {   <br style="line-height: normal; ">                          if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   <br style="line-height: normal; ">                          {   <br style="line-height: normal; ">                                printf("WSARecv() 发生了如下错误:(x)   %d\n",   WSAGetLastError());   <br style="line-height: normal; ">                                return   0;   <br style="line-height: normal; ">                          }   <br style="line-height: normal; ">                    }   <br style="line-height: normal; ">              }   <br style="line-height: normal; ">        }   <br style="line-height: normal; ">}  </span> <img src ="http://www.shnenglu.com/keigoliye/aggbug/108341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/keigoliye/" target="_blank">暗夜教父</a> 2010-02-24 13:34 <a href="http://www.shnenglu.com/keigoliye/archive/2010/02/24/108341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux环境下的Socket~程http://www.shnenglu.com/keigoliye/archive/2010/02/24/108340.html暗夜教父暗夜教父Wed, 24 Feb 2010 05:32:00 GMThttp://www.shnenglu.com/keigoliye/archive/2010/02/24/108340.htmlhttp://www.shnenglu.com/keigoliye/comments/108340.htmlhttp://www.shnenglu.com/keigoliye/archive/2010/02/24/108340.html#Feedback0http://www.shnenglu.com/keigoliye/comments/commentRss/108340.htmlhttp://www.shnenglu.com/keigoliye/services/trackbacks/108340.html什么是Socket 
  Socket接口是TCP/IP|络的APIQSocket接口定义了许多函数或例程Q程序员可以用它们来开发TCP/IP|络上的应用E序。要学Internet上的TCP/IP|络~程Q必ȝ解Socket接口?nbsp;
  Socket接口设计者最先是接口放在Unix操作pȝ里面的。如果了解Unixpȝ的输入和输出的话Q就很容易了解Socket了。网l的Socket数据传输是一U特D的I/OQSocket也是一U文件描q符。Socket也具有一个类g打开文g的函数调用Socket()Q该函数q回一个整型的Socket描述W,随后的连接徏立、数据传输等操作都是通过该Socket实现的。常用的Socketcd有两U:(x)式SocketQSOCK_STREAMQ和数据报式SocketQSOCK_DGRAMQ。流式是一U面向连接的SocketQ针对于面向q接的TCP服务应用Q数据报式Socket是一U无q接的SocketQ对应于无连接的UDP服务应用?nbsp;

Socket建立 
  Z建立SocketQ程序可以调用Socket函数Q该函数q回一个类g文g描述W的句柄。socket函数原型为:(x) 
  int socket(int domain, int type, int protocol); 
  domain指明所使用的协议族Q通常为PF_INETQ表CZ联网协议族(TCP/IP协议族)Qtype参数指定socket的类型:(x)SOCK_STREAM 或SOCK_DGRAMQSocket接口q定义了原始SocketQSOCK_RAWQ,允许E序使用低层协议Qprotocol通常赋?0"。Socket()调用q回一个整型socket描述W,你可以在后面的调用用它?nbsp;
  Socket描述W是一个指向内部数据结构的指针Q它指向描述W表入口。调用Socket函数Ӟsocket执行体将建立一个SocketQ实际上"建立一个Socket"意味着Z个Socket数据l构分配存储I间。Socket执行体ؓ(f)你管理描q符表?nbsp;
  两个|络E序之间的一个网l连接包括五U信息:(x)通信协议、本地协议地址、本C机端口、远端主机地址和远端协议端口。Socket数据l构中包含这五种信息?nbsp;

Socket配置 
  通过socket调用q回一个socket描述W后Q在使用socketq行|络传输以前Q必配|该socket。面向连接的socket客户端通过调用Connect函数在socket数据l构中保存本地和q端信息。无q接socket的客L(fng)和服务端以及(qing)面向q接socket的服务端通过调用bind函数来配|本C息?nbsp;
Bind函数socket与本Z的一个端口相兌Q随后你可以在该端口监听服务请求。Bind函数原型为:(x) 
  int bind(int sockfd,struct sockaddr *my_addr, int addrlen); 
  Sockfd是调用socket函数q回的socket描述W?my_addr是一个指向包含有本机IP地址?qing)端口号{信息的sockaddrcd的指针;addrlen常被讄为sizeof(struct sockaddr)?nbsp;
  struct sockaddrl构cd是用来保存socket信息的:(x) 
  struct sockaddr { 
   unsigned short sa_family; /* 地址族, AF_xxx */ 
char sa_data[14]; /* 14 字节的协议地址 */ 
}; 
  sa_family一般ؓ(f)AF_INETQ代表InternetQTCP/IPQ地址族;sa_data则包含该socket的IP地址和端口号?nbsp;
  另外q有一U结构类型:(x) 
  struct sockaddr_in { 
   short int sin_family; /* 地址?*/ 
   unsigned short int sin_port; /* 端口?*/ 
   struct in_addr sin_addr; /* IP地址 */ 
   unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */ 
  }; 
  q个l构更方便用。sin_zero用来sockaddr_inl构填充Cstruct sockaddr同样的长度,可以用bzero()或memset()函数其|ؓ(f)零。指向sockaddr_in 的指针和指向sockaddr的指针可以相互{换,q意味着如果一个函数所需参数cd是sockaddrӞ你可以在函数调用的时候将一个指向sockaddr_in的指针{换ؓ(f)指向sockaddr的指针;或者相反?nbsp;
  使用bind函数Ӟ可以用下面的赋值实现自动获得本机IP地址和随取一个没有被占用的端口号Q?nbsp;
  my_addr.sin_port = 0; /* pȝ随机选择一个未被用的端口?*/ 
  my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */ 
通过my_addr.sin_port|ؓ(f)0Q函C(x)自动Z选择一个未占用的端口来使用。同P通过my_addr.sin_addr.s_addr|ؓ(f)INADDR_ANYQ系l会(x)自动填入本机IP地址?nbsp;
注意在用bind函数是需要将sin_port和sin_addr转换成ؓ(f)|络字节优先序Q而sin_addr则不需要{换?nbsp;
  计算机数据存储有两种字节优先序Q高位字节优先和低位字节优先。Internet上数据以高位字节优先序在网l上传输Q所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时需要进行{换,否则׃(x)出现数据不一致?nbsp;
  下面是几个字节顺序{换函敎ͼ(x) 
·htonl()Q把32位gL字节序{换成|络字节?nbsp;
·htons()Q把16位gL字节序{换成|络字节?nbsp;
·ntohl()Q把32位g|络字节序{换成L字节?nbsp;
·ntohs()Q把16位g|络字节序{换成L字节?nbsp;
  Bind()函数在成功被调用时返?Q出现错误时q回"-1"q将errno|ؓ(f)相应的错误号。需要注意的是,在调用bind函数时一般不要将端口L(fng)为小?024的|因ؓ(f)1?024是保留端口号Q你可以选择大于1024中的M一个没有被占用的端口号?nbsp;

q接建立 
  面向q接的客L(fng)序用Connect函数来配|socketq与q端服务器徏立一个TCPq接Q其函数原型为:(x) 
  int connect(int sockfd, struct sockaddr *serv_addr,int addrlen); 
Sockfd是socket函数q回的socket描述W;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是远端地质结构的长度。Connect函数在出现错误时q回-1Qƈ且设|errno为相应的错误码。进行客L(fng)E序设计无须调用bind()Q因U情况下只需知道目的机器的IP地址Q而客户通过哪个端口与服务器建立q接q不需要关心,socket执行体ؓ(f)你的E序自动选择一个未被占用的端口Qƈ通知你的E序数据什么时候到打断口?nbsp;
  Connect函数启动和远端主机的直接q接。只有面向连接的客户E序使用socket时才需要将此socket与远端主机相q。无q接协议从不建立直接q接。面向连接的服务器也从不启动一个连接,它只是被动的在协议端口监听客L(fng)h?nbsp;
  Listen函数使socket处于被动的监听模式,qؓ(f)该socket建立一个输入数据队列,到辄服务h保存在此队列中,直到E序处理它们?nbsp;
  int listen(int sockfdQ?int backlog); 
Sockfd是Socketpȝ调用q回的socket 描述W;backlog指定在请求队列中允许的最大请求数Q进入的q接h在队列中等待accept()它们Q参考下文)。Backlog寚w列中{待服务的请求的数目q行了限Ӟ大多数系l缺省gؓ(f)20。如果一个服务请求到来时Q输入队列已满,该socket拒l连接请求,客户收C个出错信息?nbsp;
当出现错误时listen函数q回-1Qƈ|相应的errno错误码?nbsp;
  accept()函数让服务器接收客户的连接请求。在建立好输入队列后Q服务器p用accept函数Q然后睡眠ƈ{待客户的连接请求?nbsp;
  int accept(int sockfd, void *addr, int *addrlen); 
  sockfd是被监听的socket描述W,addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提接请求服务的L的信息(某台L从某个端口发hQ;addrten通常Z个指向gؓ(f)sizeof(struct sockaddr_in)的整型指针变量。出现错误时accept函数q回-1q置相应的errno倹{?nbsp;
  首先Q当accept函数监视的socket收到q接hӞsocket执行体将建立一个新的socketQ执行体这个新socket和请求连接进E的地址联系hQ收到服务请求的初始socket仍可以l在以前?socket上监听,同时可以在新的socket描述W上q行数据传输操作?nbsp;

数据传输 
  Send()和recv()q两个函数用于面向连接的socket上进行数据传输?nbsp;
  Send()函数原型为:(x) 
  int send(int sockfd, const void *msg, int len, int flags); 
Sockfd是你想用来传输数据的socket描述W;msg是一个指向要发送数据的指针QLen是以字节为单位的数据的长度;flags一般情况下|ؓ(f)0Q关于该参数的用法可参照man手册Q?nbsp;
  Send()函数q回实际上发送出的字节数Q可能会(x)于你希望发送的数据。在E序中应该将send()的返回gƲ发送的字节数进行比较。当send()q回glen不匹配时Q应该对q种情况q行处理?nbsp;
char *msg = "Hello!"; 
int len, bytes_sent; 
…… 
len = strlen(msg); 
bytes_sent = send(sockfd, msg,len,0); 
…… 
  recv()函数原型为:(x) 
  int recv(int sockfd,void *buf,int len,unsigned int flags); 
  Sockfd是接受数据的socket描述W;buf 是存放接收数据的~冲区;len是缓冲的长度。Flags也被|ؓ(f)0。Recv()q回实际上接收的字节敎ͼ当出现错误时Q返?1q置相应的errno倹{?nbsp;
Sendto()和recvfrom()用于在无q接的数据报socket方式下进行数据传输。由于本地socketq没有与q端机器建立q接Q所以在发送数据时应指明目的地址?nbsp;
sendto()函数原型为:(x) 
  int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen); 
  该函数比send()函数多了两个参数Qto表示目地机的IP地址和端口号信息Q而tolen常常被赋gؓ(f)sizeof (struct sockaddr)。Sendto 函数也返回实际发送的数据字节长度或在出现发送错误时q回-1?nbsp;
  Recvfrom()函数原型为:(x) 
  int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); 
  from是一个struct sockaddrcd的变量,该变量保存源机的IP地址?qing)端口号。fromlen常置为sizeof (struct sockaddr)。当recvfrom()q回Ӟfromlen包含实际存入from中的数据字节数。Recvfrom()函数q回接收到的字节数或当出现错误时q回-1Qƈ|相应的errno?nbsp;
如果你对数据报socket调用了connect()函数Ӟ你也可以利用send()和recv()q行数据传输Q但该socket仍然是数据报socketQƈ且利用传输层的UDP服务。但在发送或接收数据报时Q内怼(x)自动Z加上目地和源地址信息?nbsp;

l束传输 
  当所有的数据操作l束以后Q你可以调用close()函数来释放该socketQ从而停止在该socket上的M数据操作Q?nbsp;
close(sockfd); 
  你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输l进行。如你可以关闭某socket的写操作而允许l在该socket上接受数据,直至d所有数据?nbsp;
  int shutdown(int sockfd,int how); 
  Sockfd是需要关闭的socket的描q符。参?how允许为shutdown操作选择以下几种方式Q?nbsp;
  ·0-------不允许l接收数?nbsp;
  ·1-------不允许l发送数?nbsp;
·2-------不允许l发送和接收数据Q?nbsp;
·均ؓ(f)允许则调用close () 
  shutdown在操作成功时q回0Q在出现错误时返?1q置相应errno?nbsp;

面向q接的Socket实例 
  代码实例中的服务器通过socketq接向客L(fng)发送字W串"Hello, you are connected!"。只要在服务器上q行该服务器软gQ在客户端运行客戯YӞ客户端就?x)收到该字符丌Ӏ?nbsp;
  该服务器软g代码如下Q?nbsp;
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 
#define SERVPORT 3333 /*服务器监听端口号 */ 
#define BACKLOG 10 /* 最大同时连接请求数 */ 
main() 

int sockfd,client_fd; /*sock_fdQ监听socketQclient_fdQ数据传输socket */ 
 struct sockaddr_in my_addr; /* 本机地址信息 */ 
 struct sockaddr_in remote_addr; /* 客户端地址信息 */ 
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
  perror("socket创徏出错Q?); exit(1); 

my_addr.sin_family=AF_INET; 
 my_addr.sin_port=htons(SERVPORT); 
 my_addr.sin_addr.s_addr = INADDR_ANY; 
bzero(&(my_addr.sin_zero),8); 
 if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \ 
   == -1) { 
perror("bind出错Q?); 
exit(1); 

 if (listen(sockfd, BACKLOG) == -1) { 
perror("listen出错Q?); 
exit(1); 

while(1) { 
  sin_size = sizeof(struct sockaddr_in); 
  if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, \ 
  &sin_size)) == -1) { 
perror("accept出错"); 
continue; 

  printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr)); 
  if (!fork()) { /* 子进E代码段 */ 
   if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1) 
   perror("send出错Q?); 
close(client_fd); 
exit(0); 

  close(client_fd); 
  } 
 } 

  服务器的工作程是这L(fng)Q首先调用socket函数创徏一个SocketQ然后调用bind函数其与本机地址以及(qing)一个本地端口号l定Q然后调用listen在相应的socket上监听,当accpet接收C个连接服务请求时Q将生成一个新的socket。服务器昄该客h的IP地址Qƈ通过新的socket向客L(fng)发送字W串"HelloQyou are connected!"。最后关闭该socket?nbsp;
  代码实例中的fork()函数生成一个子q程来处理数据传输部分,fork()语句对于子进E返回的gؓ(f)0。所以包含fork函数的if语句是子q程代码部分Q它与if语句后面的父q程代码部分是ƈ发执行的?nbsp;

客户端程序代码如下:(x) 
#include<stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#define SERVPORT 3333 
#define MAXDATASIZE 100 /*每次最大数据传输量 */ 
main(int argc, char *argv[]){ 
 int sockfd, recvbytes; 
 char buf[MAXDATASIZE]; 
 struct hostent *host; 
 struct sockaddr_in serv_addr; 
 if (argc < 2) { 
fprintf(stderr,"Please enter the server's hostname!\n"); 
exit(1); 

 if((host=gethostbyname(argv[1]))==NULL) { 
herror("gethostbyname出错Q?); 
exit(1); 

 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 
perror("socket创徏出错Q?); 
exit(1); 

 serv_addr.sin_family=AF_INET; 
 serv_addr.sin_port=htons(SERVPORT); 
 serv_addr.sin_addr = *((struct in_addr *)host->h_addr); 
 bzero(&(serv_addr.sin_zero),8); 
 if (connect(sockfd, (struct sockaddr *)&serv_addr, \ 
   sizeof(struct sockaddr)) == -1) { 
perror("connect出错Q?); 
exit(1); 

 if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1) { 
perror("recv出错Q?); 
exit(1); 

 buf[recvbytes] = '\0'; 
 printf("Received: %s",buf); 
 close(sockfd); 

  客户端程序首先通过服务器域名获得服务器的IP地址Q然后创Z个socketQ调用connect函数与服务器建立q接Q连接成功之后接收从服务器发送过来的数据Q最后关闭socket?nbsp;
  函数gethostbyname()是完成域名{换的。由于IP地址难以记忆和读写,所以ؓ(f)了方便,Z常常用域名来表示LQ这需要进行域名和IP地址的{换。函数原型ؓ(f)Q?nbsp;
  struct hostent *gethostbyname(const char *name); 
  函数q回为hosten的结构类型,它的定义如下Q?nbsp;
  struct hostent { 
  char *h_name; /* L的官方域?*/ 
   char **h_aliases; /* 一个以NULLl尾的主机别名数l?*/ 
   int h_addrtype; /* q回的地址cdQ在Internet环境下ؓ(f)AF-INET */ 
  int h_length; /* 地址的字节长?*/ 
   char **h_addr_list; /* 一个以0l尾的数l,包含该主机的所有地址*/ 
  }; 
  #define h_addr h_addr_list[0] /*在h-addr-list中的W一个地址*/ 
  ?gethostname()调用成功Ӟq回指向struct hosten的指针,当调用失败时q回-1。当调用gethostbynameӞ你不能用perror()函数来输出错误信息,而应该用herror()函数来输出?nbsp;

  无连接的客户/服务器程序的在原理上和连接的客户/服务器是一L(fng)Q两者的区别在于无连接的客户/服务器中的客户一般不需要徏立连接,而且在发送接收数据时Q需要指定远端机的地址?nbsp;

d和非d 
  d函数在完成其指定的Q务以前不允许E序调用另一个函数。例如,E序执行一个读数据的函数调用时Q在此函数完成读操作以前不?x)执行下一E序语句。当服务器运行到accept语句Ӟ而没有客戯接服务请求到来,服务器就?x)停止在accept语句上等待连接服务请求的到来。这U情늧为阻塞(blockingQ。而非d操作则可以立卛_成。比如,如果你希望服务器仅仅注意查是否有客户在等待连接,有就接受q接Q否则就l箋做其他事情,则可以通过Socket讄为非d方式来实现。非dsocket在没有客户在{待时就使accept调用立即q回?nbsp;
  #include <unistd.h> 
  #include <fcntl.h> 
  …… 
sockfd = socket(AF_INET,SOCK_STREAM,0); 
fcntl(sockfd,F_SETFL,O_NONBLOCK)Q?nbsp;
…… 
  通过讄socket为非d方式Q可以实?轮询"若干Socket。当企图从一个没有数据等待处理的非阻塞Socketd数据Ӟ函数立卌回,q回gؓ(f)-1Qƈ|errnogؓ(f)EWOULDBLOCK。但是这U?轮询"?x)CPU处于忙等待方式,从而降低性能Q浪费系l资源。而调用select()?x)有效地解决q个问题Q它允许你把q程本n挂v来,而同时ɾpȝ内核监听所要求的一l文件描q符的Q何活动,只要认在Q何被监控的文件描q符上出现活动,select()调用返回指C文g描述W已准备好的信息Q从而实CE选出随机的变化,而不必由q程本n对输入进行测试而浪费CPU开销。Select函数原型? 
int select(int numfds,fd_set *readfds,fd_set *writefdsQ?nbsp;
fd_set *exceptfds,struct timeval *timeout); 
  其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文g描述W集合。如果你希望定是否可以从标准输入和某个socket描述W读取数据,你只需要将标准输入的文件描q符0和相应的sockdtfd加入到readfds集合中;numfds的值是需要检查的L(fng)最高的文g描述W加1Q这个例子中numfds的值应为sockfd+1Q当selectq回Ӟreadfds被修改Q指C某个文件描q符已经准备被读取,你可以通过FD_ISSSET()来测试。ؓ(f)了实现fd_set中对应的文g描述W的讄、复位和试Q它提供了一l宏Q?nbsp;
  FD_ZERO(fd_set *set)----清除一个文件描q符集; 
  FD_SET(int fd,fd_set *set)----一个文件描q符加入文g描述W集中; 
  FD_CLR(int fd,fd_set *set)----一个文件描q符从文件描q符集中清除Q?nbsp;
  FD_ISSET(int fd,fd_set *set)----试判断是否文件描q符被置位?nbsp;
  Timeout参数是一个指向struct timevalcd的指针,它可以select()在等待timeout长时间后没有文g描述W准备好卌回。struct timeval数据l构为:(x) 
  struct timeval { 
   int tv_sec; /* seconds */ 
   int tv_usec; /* microseconds */ 
}; 

POP3客户端实?nbsp;
  下面的代码实例基于POP3的客户协议,与邮件服务器q接q取回指定用户帐L(fng)邮g。与邮g服务器交互的命o(h)存储在字W串数组POPMessage中,E序通过一个do-while循环依次发送这些命令?nbsp;
#include<stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#define POP3SERVPORT 110 
#define MAXDATASIZE 4096 

main(int argc, char *argv[]){ 
int sockfd; 
struct hostent *host; 
struct sockaddr_in serv_addr; 
char *POPMessage[]={ 
"USER userid\r\n", 
"PASS password\r\n", 
"STAT\r\n", 
"LIST\r\n", 
"RETR 1\r\n", 
"DELE 1\r\n", 
"QUIT\r\n", 
NULL 
}; 
int iLength; 
int iMsg=0; 
int iEnd=0; 
char buf[MAXDATASIZE]; 

if((host=gethostbyname("your.server"))==NULL) { 
perror("gethostbyname error"); 
exit(1); 

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 
perror("socket error"); 
exit(1); 

serv_addr.sin_family=AF_INET; 
serv_addr.sin_port=htons(POP3SERVPORT); 
serv_addr.sin_addr = *((struct in_addr *)host->h_addr); 
bzero(&(serv_addr.sin_zero),8); 
if (connect(sockfd, (struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1){ 
perror("connect error"); 
exit(1); 


do { 
send(sockfd,POPMessage[iMsg],strlen(POPMessage[iMsg]),0); 
printf("have sent: %s",POPMessage[iMsg]); 

iLength=recv(sockfd,buf+iEnd,sizeof(buf)-iEnd,0); 
iEnd+=iLength; 
buf[iEnd]='\0'; 
printf("received: %s,%d\n",buf,iMsg); 

iMsg++; 
} while (POPMessage[iMsg]); 

close(sockfd); 
}

暗夜教父 2010-02-24 13:32 发表评论
]]>
91þþƷӰ| 18պҹþó| þþþþƷAV| þþƷA㽶| Ⱦþۺ| þþƷ˳| ٸþĻ| ƯޱгĻþ| þþûɫƬ| þɧ| þþѾƷre6| þþƷAV| Ʒþþþ㽶| ɫۺϾþۺ| ˺ݺۺϾþ88| þþƷƷ| þþۺϾɫۺϾ| ƷŮþøվ| þĻavŮ| ڸþþþþ| ƷۺϾþþþþ888ѿ| þ99Ʒ99þ| þþƷһ| ҹƷþӰԺ| ޹һ˾þþƷ| ޹Ʒþ66| ҹþþþС˵| þۺϺݺۺϾþۺ88| þ99޸ۿҳ| þþþùպƷվ| þŷƷ| þþþùɫAVѿͼƬ| AVպƷþþþ| þŷձƷ| þۺ97ɫֱ| þþƷ99Ʒ | þþоƷ| žžþ99ۺһ| ޹˾Ʒþþùһ | 91þþƷһ| þþþþþþŮ|