Socket

来源:百度文库 编辑:神马文学网 时间:2024/07/03 08:12:56
一 socket协议

Socket协议的形象描述

  socket的英文原义是“孔”或“插座”。在这里作为4BDS UNIX的进程通信机制,取后一种意思。socket非常类似于电话插座。以一个国家级电话网为例。电话的通话双方相当于相互通信的2个进程,区号是它的网络地址;区内一个单位的交换机相当于一台主机,主机分配给每个用户的局内号码相当于socket号。任何用户在通话之前,首先要占有一部电话机,相当于申请一个socket;同时要知道对方的号码,相当于对方有一个固定的socket。然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,还要拨对方区号,相当于给出网络地址)。对方假如在场并空闲(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机相当于关闭socket,撤消连接。

电话系统

  在电话系统中,一般用户只能感受到本地电话机和对方电话号码的存在,建立通话的过程,话音传输的过程以及整个电话系统的技术细节对他都是不透明的,这也与socket机制非常相似。socket利用网间网通信设施实现进程通信,但它对通信设施的细节毫不关心,只要通信设施能提供足够的通信能力,它就满足了。  至此,我们对socket进行了直观的描述。抽象出来,socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。在网间网内部,每一个socket用一个半相关描述:  (协议,本地地址,本地端口)  一个完整的socket有一个本地唯一的socket号,由操作系统分配。  最重要的是,socket 是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket 系统调用。客户随机申请一个socket (相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个socket号;服务器拥有全局公认的 socket ,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。  socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。服务器socket 半相关为全局所公认非常重要。读者不妨考虑一下,两个完全随机的用户进程之间如何建立通信?假如通信双方没有任何一方的socket 固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能的。  -----

Socket 接口

  Socket 接口是访问 Internet 使用得最广泛的方法。 如果你有一台刚配好TCP/IP协议的主机,其IP地址是202.120.127.201, 此时在另一台主机或同一台主机上执行ftp 202.120.127.201,显然无法建立连接。因"202.120.127.201" 这台主机没有运行FTP服务软件。同样, 在另一台或同一台主机上运行浏览软件 如Netscape,输入"http://202.120.127.201",也无法建立连接。现在,如果在这台主机上运行一个FTP服务软件(该软件将打开一个Socket, 并将其绑定到21端口),再在这台主机上运行一个Web 服务软件(该软件将打开另一个Socket,并将其绑定到80端口)。这样,在另一台主机或同一台主机上执行ftp 202.120.127.201,FTP客户软件将通过21端口来呼叫主机上由FTP 服务软件提供的Socket,与其建立连接并对话。而在netscape中输入"http://202.120.127.201"时,将通过80端口来呼叫主机上由Web服务软件提供的Socket,与其建 立连接并对话。

socket原理

  在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,象一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。  -----

[编辑本段]socket相关知识

1.什么是socket

  所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

重要的Socket API

  重要的Socket API:java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。  Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。  getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。  getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。 注意:其中getInputStream和getOutputStream方法均可能会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

2.如何开发一个Server-Client模型的程序

  开发原理:  服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。  客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。  Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

常用的Socket类型

  有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 Socket建立为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为:int socket(int domain, int type, int protocol);domain指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket的类型:SOCK_STREAM 或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol通常赋值"0"。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。 Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立一个Socket"意味着为一个Socket数据结构分配存储空间。 Socket执行体为你管理描述符表。两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。 socket在测量软件中的使用也很广泛

[编辑本段]二 socket函数

简介

  SOCKET socket( int af, int type, int protocol );  应用程序调用socket函数来创建一个能够进行网络通信的套接字。  第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET;  第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;  第三个参数指定应用程序所使用的通信协议。  该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。  下面是一个创建流套接字的例子: struct protoent *ppe; ppe=getprotobyname("tcp"); SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);

错误码

  WSANOTINITIALISED A successful WSAStartup call must occur before using this function.  WSAENETDOWN The network subsystem or the associated service provider has failed.  WSAEAFNOSUPPORT The specified address family is not supported.  WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.  WSAEMFILE No more socket descriptors are available.  WSAENOBUFS No buffer space is available. The socket cannot be created.  WSAEPROTONOSUPPORT The specified protocol is not supported.  WSAEPROTOTYPE The specified protocol is the wrong type for this socket.  WSAESOCKTNOSUPPORT The specified socket type is not supported in this address family.  Remarks  The socket function causes a socket descriptor and any related resources to be allocated and bound to a specific transport-service provider. Windows Sockets will utilize the first available service provider that supports the requested combination of address family, socket type and protocol parameters. The socket that is created will have the overlapped attribute as a default. For Microsoft operating systems, the Microsoft-specific socket option, SO_OPENTYPE, defined in Mswsock.h can affect this default. See Microsoft-specific documentation for a detailed description of SO_OPENTYPE.  Sockets without the overlapped attribute can be created by using WSASocket. All functions that allow overlapped operation (WSASend, WSARecv,WSASendTo, WSARecvFrom, and WSAIoctl) also support nonoverlapped usage on an overlapped socket if the values for parameters related to overlapped operation are NULL.  When selecting a protocol and its supporting service provider this procedure will only choose a base protocol or a protocol chain, not a protocol layer by itself. Unchained protocol layers are not considered to have partial matches on type or af either. That is, they do not lead to an error code of WSAEAFNOSUPPORT or WSAEPROTONOSUPPORT if no suitable protocol is found.  Important The manifest constant AF_UNSPEC continues to be defined in the header file but its use is strongly discouraged, as this can cause ambiguity in interpreting the value of the protocol parameter.  Connection-oriented sockets such as SOCK_STREAM provide full-duplex connections, and must be in a connected state before any data can be sent or received on it. A connection to another socket is created with a connect call. Once connected, data can be transferred using send and recv calls. When a session has been completed, a closesocket must be performed.  The communications protocols used to implement a reliable, connection-oriented socket ensure that data is not lost or duplicated. If data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, the connection is considered broken and subsequent calls will fail with the error code set to WSAETIMEDOUT.  Connectionless, message-oriented sockets allow sending and receiving of datagrams to and from arbitrary peers using sendto and recvfrom. If such a socket is connected to a specific peer, datagrams can be sent to that peer using send and can be received only from this peer using recv.  Support for sockets with type SOCK_RAW is not required, but service providers are encouraged to support raw sockets as practicable.  Notes for IrDA Sockets  The Af_irda.h header file must be explicitly included.  Only SOCK_STREAM is supported; the SOCK_DGRAM type is not supported by IrDA.  The protocol parameter is always set to 0 for IrDA.  Note On Windows NT, raw socket support requires administrative privileges.  Requirements  Windows NT/2000/XP: Included in Windows NT 3.1 and later.  Windows 95/98/Me: Included in Windows 95 and later.  Header: Declared in Winsock2.h.  Library: Use Ws2_32.lib.  See Also  Windows Sockets Programming Considerations Overview, Socket Functions, accept, bind, connect, getsockname, getsockopt, ioctlsocket, listen, recv, recvfrom, select, send, sendto, setsockopt, shutdown, WSASocket    要写网络程序就必须用 Socket ,这是程序员都知道的。而且,面试的时候,我们也会问对方会不会 Socket 编程?一般来说,很多人都会说, Socket 编程基本就是 listen , accept 以及 send , write 等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。  对于网络编程,我们也言必称 TCP/IP ,似乎其它网络协议已经不存在了。对于 TCP/IP ,我们还知道 TCP 和 UDP ,前者可以保证数据的正确和可靠性,后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的 IP 地址和端口号。除此,普通的程序员就不会知道太多了,很多时候这些知识已经够用了。最多,写服务程序的时候,会使用多线程来处理并发访问。  我们还知道如下几个事实:1 。一个指定的端口号不能被多个程序共用。比如,如果 IIS 占用了 80 端口,那么 Apache 就不能也用 80 端口了。 2 。很多防火墙只允许特定目标端口的数据包通过。 3 。服务程序在 listen 某个端口并 accept 某个连接请求后,会生成一个新的 socket 来对该请求进行处理。  于是,一个困惑了我很久的问题就产生了。如果一个 socket 创建后并与 80 端口绑定后,是否就意味着该 socket 占用了 80 端口呢?如果是这样的,那么当其 accept 一个请求后,生成的新的 socket 到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,那一定不是 80 端口了,于是以后的 TCP 数据包的目标端口就不是 80 了 -- 防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接请求和处理方式。我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为 connet80 端口而生成的?是不是 TCP 数据包里有什么特别的标志?或者防火墙记住了什么东西?  后来,我又仔细研读了 TCP/IP 的协议栈的原理,对很多概念有了更深刻的认识。比如,在 TCP 和 UDP 同属于传输层,共同架设在 IP 层(网络层)之上。而 IP 层主要负责的是在节点之间( End to End )的数据包传送,这里的节点是一台网络设备,比如计算机。因为 IP 层只负责把数据送到节点,而不能区分上面的不同应用,所以 TCP 和 UDP 协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息, UPD 协议基本就没有对 IP 层的数据进行任何的处理了。而 TCP 协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口( Slice Window ),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的 TCP 数据流,下面传送的都是一个个的 IP 数据包,需要由 TCP 协议来进行数据重组。  所以,我有理由怀疑,防火墙并没有足够的信息判断 TCP 数据包的更多信息,除了 IP 地址和端口号。而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的 IP 包来到的时候能够正确转发。  TCP/IP 只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如 Win32 编程接口一样, TCP/IP 也必须对外提供编程接口,这就是 Socket 编程接口 -- 原来是这么回事啊!  在 Socket 编程接口里,设计者提出了一个很重要的概念,那就是 socket 。这个 socket 跟文件句柄很相似,实际上在 BSD 系统里就是跟文件句柄一样存放在一样的进程句柄表里。这个 socket 其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等等。这些句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定的对象进行操作 -- 这其实是 C 语言的问题,在 C++ 语言里,这个句柄其实就是 this 指针,实际就是对象指针啦。  现在我们知道, socket 跟 TCP/IP 并没有必然的联系。 Socket 编程接口在设计的时候,就希望也能适应其他的网络协议。所以, socket 的出现只是可以更方便的使用 TCP/IP 协议栈而已,其对 TCP/IP 进行了抽象,形成了几个最基本的函数接口。比如 create , listen , accept , connect , read 和 write 等等。  现在我们明白,如果一个程序创建了一个 socket ,并让其监听 80 端口,其实是向 TCP/IP 协议栈声明了其对 80 端口的占有。以后,所有目标是 80 端口的 TCP 数据包都会转发给该程序(这里的程序,因为使用的是 Socket 编程接口,所以首先由 Socket 层来处理)。所谓 accept 函数,其实抽象的是 TCP 的连接建立过程。 accept 函数返回的新 socket 其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源 IP 和源端口,另一个是宿 IP 和宿端口。所以, accept 可以产生多个不同的 socket ,而这些 socket 里包含的宿 IP 和宿端口是不变的,变化的只是源 IP 和源端口。这样的话,这些 socket 宿端口就可以都是 80 ,而 Socket 层还是能根据源 / 宿对来准确地分辨出 IP 包和 socket 的归属关系,从而完成对 TCP/IP 协议的操作封装!而同时,放火墙的对 IP 包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。