《计算机网络:自顶向下方法》阅读笔记系列

学习套接字编程就是探讨一下网络应用程序是如何实际编写的。

先回顾一下套接字:网络应用是由一对程序(客户程序和服务器程序)组成,位于两个不同的端系统中。两个程序运行时,创建了一个客户进程、一个服务器进程,他们就是通过套接字读出或者是写入数据从而实现在彼此之间进行通信。

UDP套接字编程

在发送进程能够将数据分组推出套接字之前,当使用UDP时,必须先将目的地址附在该分组之上,目的地址包括:

  1. 目的主机的IP地址(使得路由器能够通过因特网将分组路由到目的主机)
  2. 该套接字的端口号(port number)(因为一台主机 可能运行许多网络应用进程,每个进程具有一个或多个套接字,因此当生成一个套接字时,就为它分配一个成为**端口号(port number)**的标识符)

除此之外,发送方的源地址也要附在该分组上,与目的地址类似,源地址包括源主机的IP地址和源套接字的端口号。但是,将该源地址附在分组之上的操作通常不是UDP应用程序代码所为,而是由底层操作系统自动完成。

演示示例:

1)客户从其键盘读取一行字符(数据)并将该数据向服务器发送

2)服务器接受该数据并将这些字符转换为大写

3)服务器将修改的数据发送给客户

4)客户接受修改的数据并在其监视器上将该行显示出来

简单的程序实现:

1.UDPClient.py

from socket import *
serverName = 'hostname'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_DGRAM)
message = raw_input('Input lowercase sentense:')
clientSocket.sendto(message.encode(),(serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print(modifiedMessage.decode())
clientSocket.close()

from socket import *

socket模块形成了在Python中所有网络通信的基础,使得我们能够在程序中创建套接字。

serverName = 'hostname'

serverPort = 12000

将serverName置为服务器的IP地址或者服务器的主机名,第二行将serverPort置为服务器套接字的端口号。

clientSocket = socket(AF_INET, SOCK_DGRAM)

创建客户的套接字clientSocket,第一个参数指示了地址簇,AF_INET指示了底层网络使用了IPv4,第二个参数指示了该套接字是SOCK_DGRAM类型的,意味着它是一个UDP套接字。

创建套接字时,没有指定客户套接字的端口号,相反操作系统做了这件事。

message = raw_input('Input lowercase sentense:')

采用Python的内置功能,将用户在键盘上的输入存入到message变量中。

在python3.x中对raw_input()和input()进行了整合,去除了raw_input(),仅保留了input()函数。

clientSocket.sendto(message.encode(),(serverName, serverPort))

有了套接字和报文之后,就通过该套接字向目的主机发送报文,message.encode()的作用是将报文从字符串类型转换为字节类型,因为需要向套接字中发送字节。sendto方法为报文附上目的地址并且向进程的套接字clientSocket发送结果分组。

在发送完分组之后,客户就等着接受来自服务器的数据。

modifiedMessage, serverAddress = clientSocket.recvfrom(2048)

当客户套接字收到一个来自因特网的分组时,该分组的数据被放置到变量modifiedMessage中,其源地址被放置到变量serverAddress中。

print(modifiedMessage.decode())

这行代码将报文从字节转化为字符串后,在用户的显示器上打印出来。

clientSocket.close()

最后关闭了套接字,然后关闭了该进程。

2.UDPServer.py

from socket import *
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
print("The server is ready to receive")
while True:message, clientAddress = serverSocket.recvfrom(2048)modifiedMessage = message.decode().upper()serverSocket.sendto(modifiedMessage.encode(), clientAddress)

代码开始部分与客户端类似,有很大不同的第一行代码是:

serverSocket.bind(('', serverPort))

将端口号12000与该服务器的套接字绑定在一起,说明了在服务器端为套接字分配一个端口号是代码显式实现的。这样,任何向该服务器的IP地址的端口12000发送的分组都将导向该套接字。

message, clientAddress = serverSocket.recvfrom(2048)

在接收到一个分组时,数据被放置到变量message中,其源地址被放置到clientAddress中。

modifiedMessage = message.decode().upper()

这一行代码属于业务代码,即将报文转化为字符串后,使用upper()方法将其转换为大写。

serverSocket.sendto(modifiedMessage.encode(), clientAddress)

最后将回答报文编码为字节类型后返回给客户端。

TCP套接字编程

TCP是一个面向连接的协议,意味着客户和服务器在能够开始互相发送数据之前,先要握手创建一个TCP连接。TCP连接一端与客户套接字相联系,另一端与服务器套接字相联系。在创建TCP连接时,需要将其与客户套接字地址(IP地址和端口号)和服务器套接字地址(IP地址和端口号)关联起来。使用创建的TCP连接,当一侧要向另一侧发送数据时,它只需经过其套接字将数据丢进TCP连接,而UDP在将分组丢进套接字之前必须为其附上一个目的地地址。

TCP中客户程序与服务器程序的交互过程

客户具有向服务器发起接触的任务。服务器为了能够对客户的初始接触作出反应,服务器必须已经准备好。这意味着:

  1. 与UDP中的情况一样,TCP服务器在客户试图发起接触前必须作为进程运行起来
  2. 服务器程序必须具有一个特殊的套接字,该套接字欢迎来自运行在任意主机上的客户进程的某种初始接触

在服务器进程的运行过程中,客户进程能够向服务器发起一个TCP连接,这是由客户程序通过创建一个TCP套接字完成的。在客户生成其TCP套接字时,指定了服务器中的欢迎套接字的地址,即服务器主机的IP地址及其套接字的端口号。生成其套接字后,该客户发起一个三次握手并创建与服务器的一个TCP连接。

三次握手是发生在客户进程套接字与服务器进程的欢迎套接字之间的,在这期间,服务器将生成一个新的套接字,也就是图中的连接套接字,它专门用于特定的客户。

注意区分:

  1. 欢迎套接字:这是所有要与服务器通信的客户的起始接触点
  2. 连接套接字:这是随后为与每个客户通信而生成的套接字

从应用程序的观点来看,客户套接字和服务器连接套接字直接通过一根管道连接。客户进程不仅能向它的套接字发送字节,也能从中接收字节;服务器进程不仅能从它的连接套接字接收字节,也能向其发送字节。TCP保证了其发送和接收字节的可靠性。

简单的程序实现

1.TCPClient.py

from socket import *
serverName = 'servername'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
sentence = raw_input('Input lowercase sentence:')
clientSocket.send(sentence.encode())
modifiedSentence = clientSocket.recv(1024)
print('From Server:', modifiedSentence.decode())
clientSocket.close()

clientSocket = socket(AF_INET, SOCK_STREAM)

该行创建了客户的套接字,第一个参数仍指示底层网络使用的是IPv4,第二个参数指示该套接字是SOCK_STREAM类型,表明它是一个TCP套接字。

同样,创建该客户套接字时仍未指定其端口号,因为这个操作仍是由操作系统替我们完成的。

clientSocket.connect((serverName, serverPort))

上面这一行就发起了客户和服务器之间的TCP连接,这行代码执行完后,执行三次握手,并在客户和服务器之间创建起一条TCP连接。

sentence = raw_input('Input lowercase sentence:')

与UDPClient一样,这一行是从用户获得一个句子。

clientSocket.send(sentence.encode())

通过该客户的套接字并进入TCP连接发送字符串sentence,这里没有显式地创建一个分组并为该分组附上目的地址,这是与UDP不同的一点。

modifiedSentence = clientSocket.recv(1024)

接收服务器传回来的字节。

clientSocket.close()

最后一行关闭套接字。

2.TCPServer.py

from socket import *
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to receive')
while True:connectionSocket, addr = serverSocket.accept()sentence = connectionSocket.recv(1024).decode()capitalizedSentence = sentence.upper()connectionSocket.send(capitalizedSentence.encode())connectionSocket.close()

serverSocket = socket(AF_INET, SOCK_STREAM)

与TCPClient相同的是,服务器创建了一个TCP套接字。

serverSocket.bind(('', serverPort))

与UDPServer类似,将服务器的端口号serverPort与该套接字关联起来。

serverSocket.listen(1)

serverSocket是我们的欢迎套接字,创建好这个欢迎套接字后,将等待并聆听某个客户发出的连接请求,其中的参数定义了请求连接的最大数(至少为1)。

connectionSocket, addr = serverSocket.accept()

当客户发出请求后,程序为serverSocket调用accept()方法,这在服务器中创建了一个称为connectionSocket的新套接字,由这个特定的客户专用。

connectionSocket.close()

在此程序中,执行完业务代码之后,就关闭了该连接套接字,但由于serverSocket保持打开,所以其他客户仍然可以向该服务器发出连接请求。

「计算机网络:自顶向下方法阅读笔记」套接字编程:生成网络应用相关推荐

  1. 《计算机网络—自顶向下方法》 第二章套接字编程:2.UDPping服务器

    实验描述 本编程作业的题目描述: 在这个编程作业中,你将用Python编写一个客户ping程序.该客户将发送一个简单的ping报文,接受一个从服务器返回的ping报文,并确定从该客户发送ping报文到 ...

  2. 计算机网络--自顶向下方法 学习笔记之计算机网络和因特网

    什么是Internet? 因特网的具体构成描述 因特网是一个世界范围的计算机网络,即它是一个互联了遍及全世界数十亿计算设备的网络. 有趣的因特网互联设备 数以亿计的互联计算设备:便携机.智能手机.平板 ...

  3. 认真学习系列:《计算机网络自顶向下方法》笔记

    一  应用层 1.协议原理:TCP或UDP加端口号. 然后介绍了应用层最常用的协议 2.web和http: 持续连接和非持续连接(长连接和短连接):http报文格式:http无状态,客户端浏览器通过c ...

  4. 《计算机网络自顶向下方法》笔记

    暑假期间阅读了这本书,为即将学习的专业课打下一点基础.把大致讲到的内容都概括地记下来,到时候上课后再根据所学进行补充. 感觉这本书举例挺多而且易于理解,是挺易读的一本入门书籍. 这学期结合老师和课本的 ...

  5. 《计算机网络 自顶向下方法》笔记 第二章 应用层

    第二章 应用层 2.1 应用层协议原理 网络应用是计算机网络存在的理由. 研发网络应用程序的核心是写出能够运行在不同端系统和通过网络彼此通信的程序,当研发新应用程序时,需要编写将在多台端系统上运行的软 ...

  6. 计算机网络--自顶向下方法学习笔记

    第一章 计算机网络和因特网 协议:定义了两个或多个通信实体之间交换的报文的格式和顺序,以及报文发送和/或接收一条报文或其他事件所采取的动作. 分组:将源报文划分为较小的数据块 存储转发传输:交换机能够 ...

  7. 计算机网络 自顶向下方法 学习笔记 第一章

    第一章 计算机网络和因特网 1.1 什么是因特网 1.1.1 网络 1.1.2 计算机网络 1.1.2.1 计算机网络的分类 1.1.3 互联网(从具体构成角度了解Internet) 1.1.4 协议 ...

  8. 计算机网络自顶向下方法笔记01

    <计算机网络自顶向下方法>学习笔记.之前学习过计算机网络微课,已经对计网中的很多概念都有了印象和一定的了解了,这时候再读自顶向下感觉比较轻松了.这本书没有涉及太多物理层的内容,第一章为概述 ...

  9. 计算机网络-自顶向下方法-笔记【第3章-传输层】

    计算机网络-自顶向下方法-笔记[第3章-传输层] 学习的课程及图片来源:中科大郑烇.杨坚全套<计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)>课 ...

最新文章

  1. [软件架构:设计模式系列C#篇]系列教程汇总
  2. ie下LI的间距问题
  3. 使用noode.js创建一个服务器
  4. 雷达成像技术_毫米波立体成像雷达技术研究
  5. SpringBoot 中常用注解@PathVaribale/@RequestParam/@GetMapping介绍
  6. ERROR: org.apache.hadoop.hbase.MasterNotRunningException: Retried 7 times
  7. 前端学习(3038):vue+element今日头条管理-使用请求拦截器
  8. 单片机 架构 程序 经验总结_单片机“死机”了怎么办?看看一个资深工程师的经验总结...
  9. LeetCode 345. 反转字符串中的元音字母
  10. 动态规划——命运(hdu2571)
  11. Valid Number 1
  12. 《专家速成手册》 做专家只需记住6点
  13. 计算机学院嘉年华标题,我院计算机系举办计算机嘉年华系列活动
  14. Codeforces Round #415 (Div. 2) C. Do you want a date?
  15. python如何释放对象_如何正确清理Python对象?
  16. C语言程序设计-用英文单词模拟数学计算系统
  17. 红孩儿编辑器的渲染子系统的渲染模块的函数依赖关系图
  18. 盛世昊通全新升级,引领智慧新经济
  19. 计算各种面值人民币张数
  20. [数据结构] 数组与链表的优缺点和区别

热门文章

  1. Ubuntu 开机黑屏两大原因解决办法
  2. 1. Lock (锁的)接口
  3. Python语言的优点和缺点
  4. 机械键盘中的六键无冲突和全键无冲突
  5. HTML中引入在线图片
  6. 【转】idea的文件一直在不停闪烁,并不停updating and index
  7. 高斯算法——Java实现及效率对比
  8. java中的控制层(controller)数据访问层(dao)业务逻辑层的(service)
  9. uniapp中图片宽度100%,高度自适应
  10. java读远程服务器文件,java 读取远程服务器文件