精华内容
下载资源
问答
  • 网络编程学习笔记一:Socket编程

    万次阅读 多人点赞 2013-03-21 01:11:11
    话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。 ——有感于实际编程和开源项目研究。 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与...

    “一切皆Socket!”

    话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。

    ——有感于实际编程和开源项目研究。

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的。本文的主要内容如下:

    • 1、网络中进程之间如何通信?
    • 2、Socket是什么?
    • 3、socket的基本操作
      • 3.1、socket()函数
      • 3.2、bind()函数
      • 3.3、listen()、connect()函数
      • 3.4、accept()函数
      • 3.5、read()、write()函数等
      • 3.6、close()函数
    • 4、socket中TCP的三次握手建立连接详解
    • 5、socket中TCP的四次握手释放连接详解
    • 6、一个例子(实践一下)
    • 7、留下一个问题,欢迎大家回帖回答!!!

    1、网络中进程之间如何通信?

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

    • 消息传递(管道、FIFO、消息队列)
    • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
    • 共享内存(匿名的和具名的)
    • 远程过程调用(Solaris门和Sun RPC)

    但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址可以唯一标识网络中的主机,而传输层的“协议+端口可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

    使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX  BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

    2、什么是Socket?

    上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

    socket一词的起源

    在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

    3、socket的基本操作

    既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

    3.1、socket()函数

    int socket(int domain, int type, int protocol);

     socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

    正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

    • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INETAF_INET6AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
    • type:指定socket类型。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等等(socket的类型有哪些?)。
    • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

    注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

    当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()listen()时系统会自动随机分配一个端口。

    3.2、bind()函数

    正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INETAF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    函数的三个参数分别为:

    • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
    • addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是: 
      struct sockaddr_in {
          sa_family_t    sin_family; /* address family: AF_INET */
          in_port_t      sin_port;   /* port in network byte order */
          struct in_addr sin_addr;   /* internet address */
      };
      
      /* Internet address. */
      struct in_addr {
          uint32_t       s_addr;     /* address in network byte order */
      };

      ipv6对应的是: 

      struct sockaddr_in6 { 
          sa_family_t     sin6_family;   /* AF_INET6 */ 
          in_port_t       sin6_port;     /* port number */ 
          uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
          struct in6_addr sin6_addr;     /* IPv6 address */ 
          uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
      };
      
      struct in6_addr { 
          unsigned char   s6_addr[16];   /* IPv6 address */ 
      };

      Unix域对应的是: 

      #define UNIX_PATH_MAX    108
      
      struct sockaddr_un { 
          sa_family_t sun_family;               /* AF_UNIX */ 
          char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
      };

       

    • addrlen:对应的是地址的长度。

    通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

    网络字节序与主机字节序

    主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

      a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

      b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

    所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

    3.3、listen()、connect()函数

    如果作为一个服务器,在调用socket()bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

    int listen(int sockfd, int backlog);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

    connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

    3.4、accept()函数

    TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

    注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

    3.5、read()、write()等函数

    万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

    • read()/write()
    • recv()/send()
    • readv()/writev()
    • recvmsg()/sendmsg()
    • recvfrom()/sendto()

    我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

           #include <unistd.h>
    
           ssize_t read(int fd, void *buf, size_t count);
           ssize_t write(int fd, const void *buf, size_t count);
    
           #include <sys/types.h>
           #include <sys/socket.h>
    
           ssize_t send(int sockfd, const void *buf, size_t len, int flags);
           ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    
           ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen);
           ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);
    
           ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
           ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

    write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

    其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

    3.6、close()函数

    在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

    #include <unistd.h>
    int close(int fd);

    close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

    注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

    4、socket中TCP的三次握手建立连接详解

    我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

    • 客户端向服务器发送一个SYN J
    • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
    • 客户端再想服务器发一个确认ACK K+1

    只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

    image

    图1、socket中发送的TCP三次握手

    从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

    总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

    5、socket中TCP的四次握手释放连接详解

    上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

    image

    图2、socket中发送的TCP四次握手

    图示过程如下:

    • 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
    • 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
    • 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
    • 接收到这个FIN的源发送端TCP对它进行确认。

    这样每个方向上都有一个FIN和ACK。

    6、一个例子(实践一下)

    说了这么多了,动手实践一下。下面编写一个简单的服务器、客户端(使用TCP)——服务器端一直监听本机的6666号端口,如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接并发送一条消息。

    服务器端代码:

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h>
    #define MAXLINE 4096 int main(int argc, char** argv) { int listenfd, connfd; struct sockaddr_in servaddr; 
    char buff[4096]; int n;
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(6666); 
    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){ printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    if( listen(listenfd, 10) == -1){ printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    printf("======waiting for client's request======\n"); 
    while(1){ if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){ printf("accept socket error: %s(errno: %d)",strerror(errno),errno); continue; } n = recv(connfd, buff, MAXLINE, 0); buff[n] = '\0'; 
    printf("recv msg from client: %s\n", buff); close(connfd); } close(listenfd); }

    客户端代码:

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> 
    #define MAXLINE 4096 int main(int argc, char** argv) { int sockfd, n; char recvline[4096], sendline[4096]; 
    struct sockaddr_in servaddr; if( argc != 2){ printf("usage: ./client <ipaddress>\n"); exit(0); } if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("create socket error: %s(errno: %d)\n", strerror(errno),errno); 
    exit(0); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(6666); if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){ printf("inet_pton error for %s\n",argv[1]); exit(0); } 
    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("connect error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } 
    printf("send msg to server: \n"); fgets(sendline, 4096, stdin); 
    if( send(sockfd, sendline, strlen(sendline), 0) < 0) { printf("send msg error: %s(errno: %d)\n", strerror(errno), errno); exit(0); } close(sockfd); exit(0); }

    当然上面的代码很简单,也有很多缺点,这就只是简单的演示socket的基本函数使用。其实不管有多复杂的网络程序,都使用的这些基本函数。上面的服务器使用的是迭代模式的,即只有处理完一个客户端请求才会去处理下一个客户端的请求,这样的服务器处理能力是很弱的,现实中的服务器都需要有并发处理能力!为了需要并发处理,服务器需要fork()一个新的进程或者线程去处理请求等。

    7、动动手

    留下一个问题,欢迎大家回帖回答!!!是否熟悉Linux下网络编程?如熟悉,编写如下程序完成如下功能:

    服务器端:

    接收地址192.168.100.2的客户端信息,如信息为“Client Query”,则打印“Receive Query”

    客户端:

    向地址192.168.100.168的服务器端顺序发送信息“Client Query test”,“Cleint Query”,“Client Query Quit”,然后退出。

    题目中出现的ip地址可以根据实际情况定。

    ——本文只是介绍了简单的socket编程。

    更为复杂的需要自己继续深入。

    (unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误(一个实际socket编程中遇到的问题,希望对你有帮助)

     

     

    作者:吴秦
    出处:http://www.cnblogs.com/skynet/
    本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).

    http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

     

    展开全文
  • 献给想深入学习网络编程的朋友

    千次阅读 2009-09-26 21:56:00
    C,C++网络编程学习简明指南 1. 扎实的C,C++基础知识 参考资料《C程序设计》,《C++ primer》。 2. TCP/IP协议 经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是TCP事务协议等。...

    C,C++网络编程学习简明指南
    1. 扎实的C,C++基础知识
    参考资料《C程序设计》,《C++ primer》。

    2. TCP/IP协议
    经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是TCP事务协议等。还有官方的协议文档:RFC
    当然也可以在网上下载电子书。
    经典的开源协议分析工具:Wireshark.
    简单的开源TCP/IP协议栈:LwIP,或者Linux 1.0里包含的协议栈,当然也可以看看FreeBSD的TCP/IP协议栈。

    3. 实际指导网络编程的书

    Winodws平台,经典书是《windows网络编程》第二版。
    Linux平台,经典书是W.Richard Stevens 著《UNIX网络编程》。

    4. VC++开发
    侯捷著 《深入浅出MFC》, 《windows程序设计》,《Windows核心编程》,Microsoft的MSDN。

    PS. 我自己用VC++2005企业版,安装了MSDN 2005的版本。

    我抛砖引玉,请大家积极发言。

     

     

    大家有什么好的资源,电子书,可以贴上来。有关网络编程的学习经验,心得,技巧等等,和大家一起分享。我会持续编辑添加到本楼!

    1. Linux TCP/IP 协议栈分析,这是chinaunix.net论坛里的N人写的电子书,可以在这里下载PDF版本。
    http://blog.chinaunix.net/u2/85263/showart_1810785.html

    2. 《TCP/IP详解》三卷书,PDF版本下载地址:
    《TCP/IP详解,卷1:协议》,http://www.laogu.com/ds_510.htm
    《TCP/IP详解,卷2:实现》,http://www.laogu.com/ds_511.htm
    《TCP/IP详解,卷3:tcp事务协议等》,http://www.laogu.com/ds_512.htm

    3. Wireshark
    开源的经典的协议分析工具Wireshark, http://www.wireshark.org/

    4. Winpcap( linux version: libpcap) and WinDump: tcpdump for Windows
    http://www.winpcap.org/

    5. Minix的作者,著的《计算机网络》也很经典,建议看看,这本书是很多大学的计算机专业教材。
    http://product.dangdang.com/product.aspx?product_id=20446391

     

    网络编程书籍补充以下

    C++网络编程 卷1 运用ACE和模式消除复杂性
    C++网络编程 卷2 基于ACE和框架的系统化复用
    ACE自适配通信环境中文技术文档

    Visual+C++网络高级编程
    Windows网络与通信程序设计
    精通Windows+Sockets网络开发——基于Visual+C++实现

    开源网络封装库
    ACE,ICE,asio,cppsocket,netclass,poco,SimpleSocket,socketman,Sockets
    开源下载工具
    fdm, eMulePlus,eMule
    开源FTP
    FileZilla
    开源服务器
    Apache
    网游服务器开源框架
    GNE,HawkNL,RakNet,SDL_net

    最好能参加实际的网络项目,这样能见识更多成熟的网络类库。

     

     

    平常使用的工具
    Ethereal  -------协议分析
    SockMon5  -------抓包及错误分析

     

    TCP/IP 3卷太厚了,估计大家没时间看,我推荐:
    谢希仁的《计算机网络》第5版,作者用词严谨,定义讲究,参考了大量的国外文献,
    书中图文并茂,基本原理讲得非常透彻明了,非计算机专业的读者也能读懂,而且也
    有高级一点的主题,比如p2p,音视频编解码等,但高级一点的主题没有展开来,其他
    涉及到tcp/ip协议族的都讲到,是很多高校计算机专业研究生入学考试的指定参考书。

    展开全文
  • 开始学习java网络编程

    千次阅读 2011-11-15 10:06:17
    计划用2个月时间学习基础,再用一个月深入学习,目标是掌握java网络编程,掌握一个网络架构,开发一个个人网站,(内容还没想好,可以做个文学库?)下面是网上找的一些资料: 初级:天极网教程 JAVA网络...


    网络是IT发展大势,必学之。

    计划用2个月时间学习基础,再用一个月深入学习,目标是掌握java网络编程,掌握一个网络架构,开发一个个人网站,(内容还没想好,可以做个文学库?)下面是网上找的一些资料:


    初级:天极网教程


    JAVA网络编程


    深入理解网络编程


    展开全文
  • 网络编程学习小结

    万次阅读 热门讨论 2009-08-29 13:42:00
    几种网络编程方式:ISAPI、CGI、WinInet、Winsock它们之间的区别:1) ISAPI主要是开发基于浏览器客户端与服务器端程序。效率比CGI方式高,而且也扩展了CGI没有的一些功能。(基于TCP/IP模型中的应用层)2) CGI...

    几种网络编程方式:

    ISAPICGIWinInetWinsock

    它们之间的区别:

    1  ISAPI主要是开发基于浏览器客户端与服务器端程序。效率比CGI方式高,而且也扩展了CGI没有的一些功能。(基于TCP/IP模型中的应用层)

    2  CGI主要是开发基于浏览器客户端与服务器端程序。(基于TCP/IP模型中的应用层)

    3  WinInet主要是开发客户端程序。(基于TCP/IP模型中的应用层)

    4  Winsock主要是基于socket来开发客户端与服务器端程序。(基于TCP/IP模型中的各层)要想开发低层协议的程序的话就要了解协议的报文格式。

     

    网络基础知识:

    网络硬件

    数据通讯原理 (详见http://download.csdn.net/source/1196517)

    OSI七层网络模型与TCP/IP四层网络模型 (详见http://bbs.51cto.com/topic/thread-396621.html

    网络原理和协议 (详见http://www.cnpaf.net/

    Winsock

     

    网络编程:

    建议,把机械工业出版社出的《Windows网络编程技术》看N遍后,再利用MFC或者SDK编写一些小的通信例程,然后编写较大规模的网络程序,最后你就明白了网络编程了!

     

    Windows网络编程技术》专门讨论Windows网络编程技术,覆盖Windows 95/98/NT 4/2000/CE平台。内容包括NetBIOSWindows重定向器方法、Winsock方法、客户端远程访问服务器方法。本书论述深入浅出、用大量实例详解了微软网络API函数的应用。

    TCP/IP详解,1:协议》是一本完整而详细的TCP/IP协议指南。描述了属于每一层的各个协议以及它们如何在不同操作系统中运行。

    《网络通信编程实用案例精选》是一本介绍利用vlsuaIC++进行网络通信程序开发的书籍。书中精选了大量网络实例,涵盖了本地汁算机网络编程、局域网网络通信编程、IE编程、网络通信协议编程、串口通信编程、代理服务器编程和高级网络通信编程.

    RFC文档目录:http://oss.org.cn/man/develop/rfc/default.htm

    ACEACE自适配通信环境(ADAPTIVE   Communication   Environment)是可以自由使用、开放源码的面向对象框架,在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++  Wrapper   Facade(包装外观)和框架组件,可跨越多种平台完成常见的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。ACE资料参考:http://docs.huihoo.com/ace_tao/index.html

    建议在www.codeproject.comhttp://www.codeguru.com/网站上找些老外写的网络代码研究研究,最好能参加实际的网络项目,这样能见识更多成熟的网络类库。最好能参加实际的网络项目,这样能见识更多成熟的网络类库。  

     开源网络封装库 :
    ACE,ICE,asio,cppsocket,netclass,poco,SimpleSocket,socketman,Sockets
    开源下载工具
    fdm, eMulePlus,eMule
    开源FTP
    FileZilla
    开源服务器
    Apache
    网游服务器开源框架
    GNE,HawkNL,RakNet,SDL_net

     

    网络协议分析软件:

    Sniffer工具

    Wireshark 开源的经典的协议分析工具Wireshark, http://www.wireshark.org/

    WPE -------抓包

    Ethereal  -------协议分析
    SockMon5  -------抓包及错误分析

     

    Windows网络编程细节问题:
        1. 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分)调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:

        BOOL bReuseaddr=TRUE;

      setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof

    (BOOL));

        2. 如果要已经处于连接状态的soket在调用closesocket后强制关闭,不经历TIME_WAIT的过程:

        BOOL bDontLinger = FALSE;

        setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));

        3.send(),recv()过程中有时由于网络状况等原因,发收不能预期进行,而设置收发时限:

      int nNetTimeout=1000;//1

      //发送时限

      setsockopt(socketSOL_S0CKET,SO_SNDTIMEO(char *)&nNetTimeout,sizeof(int));

      //接收时限

      setsockopt(socketSOL_S0CKET,SO_RCVTIMEO(char *)&nNetTimeout,sizeof(int));

        4.send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中发送数据和接收数据量比较大,可以设置socket缓冲区,而避免了send(),recv()不断的循环收发:

      // 接收缓冲区

      int nRecvBuf=32*1024;//设置为32K

      setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));

      //发送缓冲区

      int nSendBuf=32*1024;//设置为32K

      setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));

      5. 如果在发送数据的时,希望不经历由系统缓冲区到socket缓冲区的拷贝而影响程序的性能:

      int nZero=0;

      setsockopt(socketSOL_S0CKET,SO_SNDBUF(char *)&nZero,sizeof(nZero));

      6.同上在recv()完成上述功能(默认情况是将socket缓冲区的内容拷贝到系统缓冲区):

      int nZero=0;

      setsockopt(socketSOL_S0CKET,SO_RCVBUF(char *)&nZero,sizeof(int));

      7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:

      BOOL bBroadcast=TRUE;

      setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));

      8.client连接服务器过程中,如果处于非阻塞模式下的socketconnect()的过程中可以设置connect()延时,直到accpet()被呼叫(本函数设置只有在非阻塞的过程中有显著的作用,在阻塞的函数调用中作用不大)

      BOOL bConditionalAccept=TRUE;

      setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)

    &bConditionalAccept,sizeof(BOOL));

      9.如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们一般采取的措施是"从容关闭"shutdown(s,SD_BOTH),但是数据是肯定丢失了,如何设置让程序满足具体应用的要求(即让没发完的数据发送出去后在关socket)?

      struct linger {

      u_short l_onoff;

      u_short l_linger;

      };

      linger m_sLinger;

      m_sLinger.l_onoff=1;//(closesocket()调用,但是还有数据没发送完毕的时候容许逗留)

      // 如果m_sLinger.l_onoff=0;则功能和B)作用相同;

      m_sLinger.l_linger=5;//(容许逗留的时间为5)

      setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof

    (linger));

      注意点:

          A.在设置了逗留延时,用于一个非阻塞的socket是作用不大的,最好不用;

      B.如果想要程序不经历SO_LINGER需要设置SO_DONTLINGER,或者设置l_onoff=0;

      10.一个用的比较少的是在SDI或者是Dialog的程序中,可以记录socket的调试信:

      BOOL bDebug=TRUE;

      setsockopt(s,SOL_SOCKET,SO_DEBUG,(const char*)&bDebug,sizeof(BOOL));

      11.往往通过setsockopt()设置了缓冲区大小,但还不能满足数据的传输需求,一般习惯是自己写个处理网络缓冲的类,动态分配内存。

        12#include <Afxsock.h>#include<winsock2.h>冲突问题

    解决方法:StdAfx.h 头文件中添加winsock2.h,Afxsock.h

    #include <winsock2.h> #include <Afxsock.h>

        13、获取数据包,一般来说想获取数据包可以使用IP_HDRINCL选项,但是在Windows 2000/XPsetsockopt()IP_HDRINCL是个不合法的选项,但是可以使用 WSAIoctl() 函数调用SIO_RCVALL捕获IP数据包。简单步骤如下:
    1)
    Create a raw socket.
    2)
    Bind the socket to the local IP over which the traffic is to be sniffed.
    3)
    WSAIoctl() the socket with SIO_RCVALL to give it sniffing powers.
    4)
    Put the socket in an infinite loop of recvfrom.
    5)
    n' joy! the Buffer from recvfrom.

        14IPTCPUDPICMP数据包格式
    /*The IP header */
    typedef struct tagIPHEADER{
     unsigned char version:4;
     unsigned char header_len:4;
     unsigned char tos;
     unsigned short total_len;
     unsigned short ident;
     unsigned short flags;
     unsigned char ttl;
     unsigned char proto;
     unsigned short checksum;
     unsigned int sourceIP;
     unsigned int destIP;
    }IPHEADER;


    struct TCPPacketHead{
     WORD SourPort;
     WORD DestPort;
     DWORD SeqNo;
     DWORD AckNo;
     BYTE HLen;
     BYTE Flag;
     WORD WndSize;
     WORD ChkSum;
     WORD UrgPtr;
    };

    struct ICMPPacketHead {
     BYTE Type;
     BYTE Code;
     WORD ChkSum;
    };

    struct UDPPacketHead {
     WORD SourPort;
     WORD DestPort;
     WORD Len;
     WORD ChkSum;
    };

     

        15、几种winsock I/O模型比较:
    select模型核心就是select函数,它可用于判断套接字上是否存在数据,或者能否向一个套接字写入数据。这个
    函数可以有效地防止应用程序在套接字处于阻塞模式中时,send或recv进入阻塞状态;同时也可以防止产生大量的WSAEWOULDBLOCK错误select的优势是能够从单个线程的多个套接字上进行多重连接及I/O。

    WSAAsyncSelect 模型是以消息机制为基础,能够处理一定的客户连接量,但是扩展性也不是很好。因为消息泵很快就会阻塞,降低了消息处理的速度。WSAAsyncSelect和WSAEventSelect模型提供了读写数据能力的异步通知,但他们不提供异步数据传送,而重叠及完成端口提供异步数据的传送。

    WSAEventSelect 模型以时间为基础的网络事件通知,但是与WSAAsyncSelect不同的是,它主要是由事件对象句柄完成的,而不是通过窗口。但是一个线程只能等待64个事件(需要开辟多个线程解决),伸缩性不如完成端口。

    重叠模型可以使程序能达到更佳的系统性能。基本设计原理就是让应用程序使用重叠的数据结构,一次投递一个或多个I/O请求。针对这些提交的请求,在他们完成之后,应用程序可为他们提供服务。它又分为两种实现方法:事件通知和完成例程。重叠I/O模型事件通知依赖于等待事件通知的线程数(WSAWaitForMultipleEvents调用的每个线程,该I/O模型一次最多都只能支持6 4个套接字。),处理客户通信时,大量线程上下文的切换是它们共同的制约因素。

    完成端口提供了最好的伸缩性,往往可以使系统达到最好的性能,是处理成千上万的套接字的首选。从本质上说,完成端口模型要求创建一个windows完成端口对象,该对象通过指定数量的线程,对重叠I/O请求进行管理,以便为已经完成的重叠I/O请求提供服务。但是完成端口只是支持NT系统、WIN2000系统。

    重叠模型和完成端口模型的应用程序通知缓冲区收发系统直接使用数据,也就是说,如果应用程序投递了一个10KB大小的缓冲区来接收数据,且数据已经到达套接字,则该数据将直接被拷贝到投递的缓冲区。 而select模型、WSAAsyncSelect 模型、WSAEventSelect 模型,数据到达并拷贝到单套接字接收缓冲区中,此时应用程序会被告知可以读入的容量。当应用程序调用接收函数之后,数据才从单套接字缓冲区拷贝到应用程序的缓冲区,差别就体现出来了。

     

        16、服务器与客户端IO模型选择

    对于如何挑选最适合自己应用程序的I/O模型已经很明晰了。同开发一个简单的运行多线程的锁定模式应用相比,其他每种I/O模型都需要更为复杂的编程工作。因此,针对客户机和服务器应用开发模型的选择,有以下原则

    1). 客户端

    若打算开发一个客户机应用,令其同时管理一个或多个套接字,那么建议采用重叠I/O或WSAEventSelect模型

    ,以便在一定程度上提升性能。然而,假如开发的是一个以Windows为基础的应用程序,要进行窗口消息的管理,那么WSAAsyncSelect模型恐怕是一种最好的选择,因为WSAAsyncSelect本身便是从Windows消息模型借鉴来的。采用这种模型,程序需具备消息处理功能。

    2). 服务器端

    若开发的是一个服务器应用,要在一个给定的时间,同时控制多个套接字,建议采用重叠I/O模型,这同样是从性能角度考虑的。但是,如果服务器在任何给定的时间,都会为大量I/O请求提供服务,便应考虑使用I/O完成端口模型,从而获得更佳的性能。

        17、shutdownclosesocket区别

    shutdown 从容关闭,为了保证通信双方都能够收到应用程序发出的所有数据,一个合格的应用程序的做法是通知接受双发都不在发送数据!这就是所谓的“正常关闭”套接字的方法,而这个方法就是由shutdown函数,传递给它的参数有SD_RECEIVE,SD_SEND,SD_BOTH三种,如果是SD_RECEIVE就表示不允许再对此套接字调用接受函数。这对于协议层没有影响,另外对于tcp套接字来说,无论数据是在等候接受还是即将抵达,都要重置连接(注意对于udp协议来说,仍然接受并排列传入的数据,因此udp套接字而言shutdown毫无意义)。如果选择SE_SEND,则表示不允许再调用发送函数。对于tcp套接字来说,这意味着会在所有数据发送出并得到接受端确认后产生一个FIN包。如果指定SD_BOTH,答案不言而喻。  
    closesocket
    正式关闭,关闭连接,释放所有相关的资源。因为无连接协议没有连接,所以不会有正式关闭和从容关闭,直接调用closesocket函数。

        18、TCP链接三次握手、终止链接四次握手

     

     

        19、getpeername 、getsockname

    getpeername 函数用于获得通信方的套接字地址信息,该信息上关于已建立连接的那个套接字的。
    getsockname 函数是getpeername的对应函数。它返回的是指定套接字的本地接口的地址信息。

        20、MFC下CSocket编程注意事项

    1)、在使用MFC编写socket程序时,必须要包含<afxsock.h>都文件。
    2)、AfxSocketInit() 这个函数,在使用CSocket前一定要先调用该函数,否则使用CSocket会出错。
    3)、CSocket::Create 的接口就是, 实现上还执行了 CSocket::Bind , 非常不容易被发现。如果是以 Create 方
    法初始化的前提下不能再调用 Bind ,要不一定出错。一般写服务器程序都不要用Create 为好,用下面的

    CSocket::Socket 初始化然后Bind。

        21、winsock   有两个不同的版本

    winsock   有两个不同的版本,第一版很old了,win95时代的,win2000后推崇第二版winsock   2,   出了主板本号外,还有子版本号,这些功能上有差别,winsock2   支持原始套接字编程,   MFC   还封装了winsock,使用WINSOCK.h   要用到WSOCK32.LIB,   还有一些扩展api功能,需要MSWSOCK.h   MSWSOCK.DLL  。 现在winsock.h   winsock2.h   都用ws2_32.lib。

       22、sockaddr_in , sockaddr , in_addr区别
    struct   sockaddr   { 
                    unsigned   short   sa_family;    
                    char   sa_data[14];    
            }; 
      上面是通用的socket地址,具体到Internet   socket,用下面的结构,二者可以进行类型转换 
            
      struct   sockaddr_in   { 
                    short   int   sin_family;    
                    unsigned   short   int   sin_port;    
                    struct   in_addr   sin_addr;    
                    unsigned   char   sin_zero[8];    
            }; 
            struct   in_addr就是32位IP地址。 
            struct   in_addr   { 
                    union {
                            struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                            struct { u_short s_w1,s_w2; } S_un_w;
                            u_long S_addr;
                    } S_un;

                    #define s_addr  S_un.S_addr
            }; 
       inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。

    填值的时候使用sockaddr_in结构,而作为函数(如socket, listen, bind等)的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。

    通常的用法是: 
      int   sockfd; 
      struct   sockaddr_in   my_addr; 
      sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);    
      
      my_addr.sin_family   =   AF_INET;    
      my_addr.sin_port   =   htons(MYPORT);    
      my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1"); 
      
      bzero(&(my_addr.sin_zero),   8);    
       
      bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));
    想来你是要进行网络编程,使用socket, listen, bind等函数。你只要记住,填值的时候使用sockaddr_in结构,而
    作为函数的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。 
       23、几个特殊的地址

    INADDR_LOOPBACK   (127.0.0.1)   总是代表经由回环设备的本地主机;   INADDR_ANY  

    (0.0.0.0)   表示任何可绑定的地址;   INADDR_BROADCAST   (255.255.255.255)   表示任何主机。
    INADDR_ANY 的具体含义是,绑定到0.0.0.0。此时,对所有的地址都将是有效的,如果系统考虑冗余,采用
    多个网卡的话,那么使用此种bind,将在所有网卡上进行绑定。在这种情况下,你可以收到发送到所有有效地址上数据包。
    例如:
    SOCKADDR_IN Local;
    Local.sin_addr.s_addr = htonl(INADDR_ANY);
    另外一种方式如下:
    SOCKADDR_IN Local;
    hostent* thisHost = gethostbyname("");
    char* ip = inet_ntoa(*(struct in_addr *)*thisHost->h_addr_list);
    Local.sin_addr.s_addr = inet_addr(ip);
    在这种方式下,将在系统中当前第一个可用地址上进行绑定。在多网卡的环境下,可能会出问题。

       24、常见协议

    FTP协议:http://blog.csdn.net/superman419/archive/2009/04/10/4063476.aspx
    SMTP协议:http://www.cnpaf.net/class/smtp/
    POP3协议:http://www.cnpaf.net/class/pop3/
    http://www.yesky.com/20020305/1600243.shtml
    ICMP协议:http://blog.csdn.net/byxdaz/archive/2007/08/01/1720971.aspx
    RAS协议:http://blog.ixpub.net/html/94/10181094-31509.html
    TAPI协议:http://blog.csdn.net/chszs/archive/2008/12/08/3475908.aspx
    Telnet协议:http://www.cnblogs.com/liuweijian/archive/2005/09/12/235493.html
    HTTP协议:http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html
    代理协议socks:http://blog.csdn.net/byxdaz/archive/2010/03/31/5439291.aspx

     25、为什么需要htons(), ntohl(), ntohs(),htons() 函数?
    在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数。

    网络字节顺序与本地字节顺序之间的转换函数:

          htonl()--"Host to Network Long"
          ntohl()--"Network to Host Long"
          htons()--"Host to Network Short"
          ntohs()--"Network to Host Short"
     

    之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO

    网络字节顺序NBO(Network Byte Order):
          按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。

    主机字节顺序(HBO,Host Byte Order):
          不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
    如 Intel   x86结构下,short型数0x1234表示为34   12, int型数0x12345678表示为78   56   34   12  
    如IBM   power PC结构下,short型数0x1234表示为12   34, int型数0x12345678表示为12   34   56   78
    由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power   pc那样的顺序 。在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换。

    26如何查询端口被占用的程序

    大家在启动服务器时,有时正常启动有时又启动不了是怎么回事呢??那为什么关掉迅雷等软件就又好了呢??现在就来给大家讲解一下,

    这些端口如果被其他程序占用就不能正常启动,比如有时启动时会提示WEB启动失败,其实就是80端口被占用了,而迅雷等下载软件恰恰就是占用了80端口,关掉就行了。但有时迅雷等都没有开也启动不了,那就是别的东西占用了,那怎么办呢?我来叫你查看端口并关掉的方法。
    1.
    在开始--运行   里面输入cmd点回车,会出现运行窗口。
    2.
    在提示符后输入netstat -ano回车,找到tcp 80端口对应的pid,比如1484.
    3.ctrl+alt+del
    打开任务管理器,选进程,这里有很多正在运行的程序怎么找?别急点上面的   查看--选择列--PID(进程标示符)前面打钩。好了,下面的进程前面都有了PID号码。这时上一步找到的PID就有用了,找到1484,比如PEER.EXE什么的,结束进程吧。这时再开服务器,看WEB可以启动了!


    27、TCP连接探测中的Keepalive和心跳包
    如何及时有效地检测到一方的非正常断开,一直有两种技术可以运用。一种是由TCP协议层实现的Keepalive,另一种是由应用层自己实现的心跳包。
    TCP默认并不开启Keepalive功能,因为开启Keepalive功能需要消耗额外的宽带和流量,尽管这微不足道,但在按流量计费的环境下增加了费用,另一方面,Keepalive设置不合理时可能会因为短暂的网络波动而断开健康的TCP连接。并且,默认的Keepalive超时需要7,200,000 milliseconds,即2小时,探测次数为5次。
    对于实用的程序来说,2小时的空闲时间太长。因此,我们需要手工开启Keepalive功能并设置合理的Keepalive参数。
    // 开启KeepAlive
    BOOL bKeepAlive = TRUE;
    int nRet = ::setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));
    if (nRet == SOCKET_ERROR)
    {
    return FALSE;
    }
    // 设置KeepAlive参数
    tcp_keepalive alive_in = {0};
    tcp_keepalive alive_out = {0};
    alive_in.keepalivetime = 5000;    // 开始首次KeepAlive探测前的TCP空闭时间
    alive_in.keepaliveinterval = 1000;  // 两次KeepAlive探测间的时间间隔
    alive_in.onoff = TRUE;
    unsigned long ulBytesReturn = 0;
    nRet = WSAIoctl(socket_handle, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),
    &alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);
    if(nRet == SOCKET_ERROR)
    {
    return FALSE;
    }
    windows和linux下Keepalive设置方法,参考:http://blog.csdn.net/dongfangyu/article/details/5537781

    TCP的keepalive和HTTP的keepalive之间的关系?
    TCP 的 SO_KEEPALIVE 确切的应该叫做 is_keep_alive?,它是一个探测服务,由内核完成的。
    当一端 recv(socket, ...) 时,如果对端一直没有消息返回,就会一直阻塞,本端根本不知道对端处于什么状态。所以本端可以周期发一个探测包,对端如果一定时间没有返回确认包,则认为对端已经断开连接, recv 会返回,不再继续阻塞。
    HTTP 的 keepalive 是双方通过 "Connection: keep-alive" 数据头来建立长连接,每次发送完请求不关闭套接字,而是继续下一次循环的 recv(),等待对端继续发送数据。如果设置了超时时间,那么 recv() 返回,关闭连接。
    TCP 的 SO_KEEPALIVE,当网络突然中断时,用来及时探测对端断开,避免无限制阻塞 recv。
    HTTP 的 keepalive,是双方约定长连接、还是收完一次数据后立刻关闭套接字。


    展开全文
  • MFC网络编程学习

    万次阅读 2010-07-19 19:33:00
    这两天学习了MFC网络编程,发现其实网络编程好像也没有想象中的那么难,做个梳理如下: 网络编程人员可以调用windows操作系统套接字访问通信协议,套接字存在与通信区域中,windows套接字只支持一个通信...
  • Java网络编程与NIO学习总结

    千次阅读 2018-06-29 14:43:33
    Java网络编程与NIO学习总结 这篇总结主要是基于我之前Java网络编程与NIO系列文章而形成的的。主要是把重要的知识点用自己的话说了一遍,可能会有一些错误,还望见谅和指点。谢谢 更多详细内容可以查看我的专栏...
  • C++网络编程学习指南

    千次阅读 2015-10-24 17:28:18
    Linux平台,经典书是W.Richard Stevens 著《UNIX网络编程》。 4. VC++开发 侯捷著 《深入浅出MFC》, 《windows程序设计》,《Windows核心编程》,Microsoft的MSDN 网络编程书籍补充以下 ...
  • C++ 网络编程学习指南

    千次阅读 2014-03-19 13:17:53
    C,C++网络编程学习简明指南 1. 扎实的C,C++基础知识 参考资料《C程序设计》,《C++ primer》。 2. TCP/IP协议 经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是...
  • 006_《深入Delphi6 网络编程

    千次阅读 2010-11-19 09:02:00
    并通过程序实例浅显易懂地说明各组件及WinSock API在Delphi环境下的网络编程,能够帮助读者清楚地掌握Delphi程序设计的精髓,书中配有范例光盘,以供读者学习参考。
  • 谈一谈网络编程学习经验

    千次阅读 2012-08-21 17:42:09
    谈一谈网络编程学习经验 giantchen@gmail.com blog.csdn.net/Solstice PDF 版下载:https://github.com/downloads/chenshuo/documents/LearningNetworkProgramming.pdf 本文谈一谈我在学习网络编程方面的一些...
  • 【带你入门】java网络编程

    万次阅读 多人点赞 2018-02-18 12:10:41
    网络编程网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。在 学习网络编程以前,很多初学者可能觉得网络编程是...
  • 课程聚焦Java性能调优的核心知识点,以真实场景项目实战为导向,循序渐进,深入浅出的了解Java网络编程,讲解Java这门使用广泛的编程语言,助你能够游刃有余地游走在这些技术之中。
  • 老曹眼中的网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为我们拥有网络。网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界。 然而,网络的无标度...
  • 浅谈如何学习网络编程

    万次阅读 2010-04-25 09:00:00
    如何学习网络编程?这是我的经验之谈,我从来就没有系统的学习网络编程(非科班么),学习过程中走了不少弯路。最近在读经典的《Linux程序设计(第3版)》,第十五章讲的是套接字Socket编程,读完之后,产生了一些...
  • 基于Socket网络编程

    千次阅读 多人点赞 2017-06-22 13:16:22
    2.基于TCP协议的网络编程模型(一)Socket是什么 1、C/S架构与socket的关系:我们学习socket就是为了完成C/S架构的开发 2、C/S架构的软件(软件属于应用层)是基于网络进行通信的,网络的核心即一堆协议,协议即...
  • 谈一谈网络编程学习经验(06-08更新)

    万次阅读 多人点赞 2011-06-06 08:41:00
    谈一谈网络编程学习经验 陈硕 giantchen@gmail.com blog.csdn.net/Solstice 2011-06-06 PDF 版下载:https://github.com/downloads/chenshuo/documents/LearningNetworkProgramming.pdf本文谈一谈我在学习网络编程...
  • 谈一谈网络编程学习经验(陈硕)

    万次阅读 2012-02-18 13:46:16
     本文谈一谈我在学习网络编程方面的一些个人经验。“网络编程”这个术语的范围很广,本文指用Sockets API 开发基于TCP/IP的网络应用程序,具体定义见“网络编程的各种任务角色”一节。  受限于本人的经历和经验,...
  • 学习网络编程的十个步骤

    千次阅读 2011-11-09 09:23:43
     经过多年的网络编程实践之后,个人觉得初学网络编程者可以从以下几个步骤开展:  1)下载一个可以互动的学习工具,通过这个与这个工具互动,我们可以及时的学到每个api的结果如果。我个人强烈推荐一个互动好...
  • 网络编程二-LINUX网络IO模型

    万次阅读 2019-08-10 10:24:46
    前言:网络编程里通用常识 一、同步和异步与阻塞和非阻塞 同步和异步 阻塞和非阻塞 两者的组合 二、五种I/O模型 阻塞I/O模型 非阻塞IO模型 IO复用模型 信号驱动IO 异步IO模型 5个I/O模型的比较 今天台风...
  • Java网络编程详解

    万次阅读 多人点赞 2014-09-10 17:55:34
     网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。  在 学习网络编程以前,很多初学者可能觉得网络编程是...
  • C,C++网络编程学习指南

    千次阅读 2012-03-04 11:14:11
    有关网络编程学习经验,心得,技巧等等,和大家一起分享。我会持续编辑添加到本楼! 1. Linux TCP/IP 协议栈分析 ,这是chinaunix.net论坛里的N人写的电子书,可以在这里下载PDF版本。 ...
  • Python网络编程攻略

    千次阅读 2019-05-27 19:16:10
    本书全面介绍了Python网络编程涉及的重要问题,包括网络编程、系统和网络管理、网络监控以及Web应用开发。作者通过70多篇攻略,清晰简明地描述了各种网络任务和问题,提出了可用于多种场景的解决方案,并细致地分析...
  • 网络编程学习笔记--1.socket可读可写条件

    千次阅读 多人点赞 2015-06-12 20:51:34
    socket可读可写条件,经常做为面试题被问,因为它考察被面试者对网络编程的基础了解的是不是够深入。 要了解socket可读可写条件,我们先了解几个概念: 1.接收缓存区低水位标记(用于读)和发送缓存区低水位标记...
  • 网络编程怎么学

    千次阅读 2017-11-28 09:50:59
    1.网络编程怎么学?我接手了前辈留下来的业务流程调度软件,需要和多台服务器上十多个软件进行网络通信,进行作业时间表的定时分发,设备和软件状态实时监视。 使用技术包括:消息中间件,多线程(包括定时器),...
  • perl网络编程学习系列:Net:FTP

    千次阅读 2007-03-30 20:37:00
    对于提高编程语言的水平,熟练使用各种开发库是必经之路网络编程中涉及很多,自己写个小例子供学习使用use Net::FTP;use constant HOST=> 192.168.128.3;use constant DIR=>/home/corersky/study/perl;use constant ...
  • Windows网络编程

    万次阅读 2007-12-13 16:58:00
    同时,我也希望,能为众多初学网络编程的人提供一点帮助,因为我开始学习网络编程的时候,能找到的资料就很少。当然,花钱可以买到翻译版本的书:) 首先向大家推荐一本很好的参考书,Network Pro
  • 网络编程基础概述

    千次阅读 2011-12-27 19:59:16
    网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。 在 学习网络编程以前,很多初学者可能觉得网络编程是比较...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,270
精华内容 55,308
关键字:

网络编程深入学习