基于socket的TCP、UDP 编程(附带源代码)

         网络上的两个程序t通信通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。

       使用套接字通信的有TCP和UDP两种协议。两种协议共用基本的socket函数接口。

       首先说明TCP使用socket函数通信的过程。

       TCP套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

       TCP通信时,必须进行以下三步:

    (1)服务器监听。服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。(服务器端使用listen函数将服务器置于监听状态,listen函数要与accept函数一起使用。)

    (2)客户端请求。是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后才向服务器端套接字提出连接请求。(客户端必须使用connect函数来连接服务器)。

    (3)连接确认。当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。此后服务器端套接字继续处于监听状态,接收其他客户端套接字的连接请求。(这一步使用到了accept函数进行处理,实际上accept是TCP三次握手的核心,与connect函数共同完成了三次握手中的重要部分)。

    下面针对TCP、UDP中使用的socket函数进行说明。

    (1)socket函数。

     TCP和UDP都得使用socket函数来创建套接字。

    socket函数用于新建套接字,新建好的套接字端口号和IP地址都是空的。TCP和UDP无论服务器端还是客户端,都必须使用到此函数。如何绑定到具体的端口和IP地址请参考     后文bind函数。

     第一个参数:代表协议族。一般选择AF_INET,代表是IPv4协议。

     第二个参数:socket类型。一般选择SOCK_STREAM: TCP协议,SOCK_DGRAM:UDP。

     最后一个参 数。一般是0。0时会自动选择第二个参数类型对应的默认协议。如果不是0,那么第二个参数和第三个参数选择时要对应起来,如SOCK_STREAM时要选择              IPPROTO_TCP,SOCK_DGRAM,IPPROTO_UDP。不可以乱选,造成不匹配。

     (2)bind函数。

       TCP和UDP都必须在服务器端使用到此函数,来指明套接字的本地地址(本地端口号+本地IP地址)。

       TCP和UDP,在客户端可以选用此函数,但是客户端一般无需绑定端口,因为客户端不关心自己的端口号是多少,如果不调用bind,操作系统内核会自动分配一个端口。如       果确实需要一个确定端口号,则也须采用此函数绑定端口号。

      服务器端作为被动连接的一方,根据TCP/IP通信中 “IPAddress+端口号”的通信原理,服务器端必须将服务器端套接字与端口绑定绑定,同时将绑定的端口和本地IP告知客户      端。鉴于此函数参数容易理解,不多解释。

      (3)connect函数。

       TCP必用,UDP可选用。connect函数是客户端使用的连接服务器的函数。一旦与远程服务器主机取得连接,此后就不必在每次发送数据时都指定远程主机指定目的地址。

      在UDP通信中,服务器端不使用listen将套接字置于侦听状态。UDP通信中客户端可以不用取得连接后在发送数据,因此UDP协议的客户端可以不用connect。在UDP通信中,发送数据时可以采用sendto函数指定目的地址。后续会专门提到sendto 、recvfrom、send、recv区别。

由于TCP是面向连接的通信,所以必须使用connect用于和服务器端取得联系。TCP通信中,客户端执行了connect后,客户端的socket就有了连接对象(与服务器中的侦听套接字连接),至此,套接字始终与服务器监听套接字保持连接状态,直到对方accept处理完成了这个连接,并在服务器端将连接对象转向新建的套接字(操作系统完成,用户看不到)。

   (4)listen函数。

      listen是TCP协议中服务器端必须使用的函数。由于UDP协议采用无连接的服务,所以不会使用到此函数。 在TCP服务器中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。 listen函数一般在调用bind之后 , 调用accept之前调用。

     listen函数有两参数。第一个参数代表一个已绑定但未被客户端连接的套接字描述符。第二个参数是等待连接队列的最大长度,可以认为开启的队列,可以同时处理的连接数目,一旦连接处理成功,就会从队列中移除。如果你将参数定为10, 当有15个连接同时请求的时候,前面10个连接请求就被放置在请求队列中,但后面5个请求被拒绝。千万要注意:这个10并不是表示客户端最大的连接数为10, 实际上可以有很多很多的客户端,但是只要不是同时超过设定值进行请求连接就行。在经典书籍《TCP/IP详解 卷1:协议》的Page195有所解释。此参数设定在TCP层接收链接的缓冲池的最大个数。当客户链接请求大于这个个数(缓冲池满),其它的未进入链接缓冲池的客户端在TCP层上TCP模块会自动重新链接,直到超时(大约57秒后)。客户端连接(connect)完成时,服务器端要从TCP层的连接缓冲池中移出一个(accept函数实现),只要accept处理完成一个connect就会将缓冲池空一个,此时可以接着将新的connect连接送入过来处理。

  (5)accept函数。

     accept函数是TCP协议中服务器端必须使用的函数。用于处理来自服务器的连接。可以说accept函数是所有之中最复杂的函数,但是它的具体功能已经由操作系统帮我们实现了。

     主服务器程序(位于服务器端)调用accept函数等待着客户端的connect连接,一旦客户端发起连接,此时就会为这个连接创建一个新的套接字并通过accept函数返回新建socket的描述符.,这个新建的套接字此时已经和发起连接的客户端取得连接。此时我们在开启一个从线程,通过此新建的套接字用于和客户端的通信,专门处理客户端和服务器之间的数据。我们将新建的套接字称之为通信套接字,服务器初始新建并listen之后的套接字专门用于处理连接,我们称之为侦听连接套接字。侦听连接套接字在accept处理一个连接之后,就将新建的通信套接字送入开启的新线程中,在子线程间和客户端进行数据通信,主线程而它专注于处理远端连接请求(使用accept函数

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值