基于tcp\/ip协议的网络编程(基于tcp协议的协议)
Python网络编程 -- TCP/IP
首先放出一个 TCP/IP 的程序,这里是单线程服务器与客户端,在多线程一节会放上多线程的TCP/IP服务程序。
这里将服务端和客户端放到同一个程序当中,方便对比服务端与客户端的不同。
TCP/IP是因特网的通信协议,其参考OSI模型,也采用了分层的方式,对每一层制定了相应的标准。
网际协议(IP)是为全世界通过互联网连接的计算机赋予统一地址系统的机制,它使得数据包能够从互联网的一端发送至另一端,如 130.207.244.244,为了便于记忆,常用主机名代替IP地址,例如 baidu.com。
UDP (User Datagram Protocol,用户数据报协议) 解决了上述第一个问题,通过端口号来实现了多路复用(用不同的端口区分不同的应用程序)但是使用UDP协议的网络程序需要自己处理丢包、重包和包的乱序问题。
TCP (Transmission Control Protocol,传输控制协议) 解决了上述两个问题,同样使用端口号实现了复用。
TCP 实现可靠连接的方法:
socket通信模型及 TCP 通信过程如下两张图。
[图片上传失败...(image-6d947d-1610703914730)]
[图片上传失败...(image-30b472-1610703914730)]
socket.getaddrinfo(host, port, family, socktype, proto, flags)
返回: [(family, socktype, proto, cannonname, sockaddr), ] 由元组组成的列表。
family:表示socket使用的协议簇, AF_UNIX : 1, AF_INET: 2, AF_INET6 : 10。 0 表示不指定。
socktype: socket 的类型, SOCK_STREAM : 1, SOCK_DGRAM : 2, SOCK_RAW : 3
proto: 协议, 套接字所用的协议,如果不指定, 则为 0。 IPPROTO_TCP : 6, IPPRTOTO_UDP : 17
flags:标记,限制返回内容。 AI_ADDRCONFIG 把计算机无法连接的所有地址都过滤掉(如果一个机构既有IPv4,又有IPv6,而主机只有IPv4,则会把 IPv6过滤掉)
AI _V4MAPPED, 如果本机只有IPv6,服务却只有IPv4,这个标记会将 IPv4地址重新编码为可实际使用的IPv6地址。
AI_CANONNAME,返回规范主机名:cannonname。
getaddrinfo(None, 'smtp', 0, socket.SOCK_STREAM, 0, socket.AP_PASSIVE)
getaddrinfo('', 'ftp', 0, 'socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)
利用已经通信的套接字名提供给getaddrinfo
mysock = server_sock.accept()
addr, port = mysock.getpeername()
getaddrinfo(addr, port, mysock.family, mysock.type, mysock.proto, socket.AI_CANONNAME)
TCP 数据发送模式:
由于 TCP 是发送流式数据,并且会自动分割发送的数据包,而且在 recv 的时候会阻塞进程,直到接收到数据为止,因此会出现死锁现象,及通信双方都在等待接收数据导致无法响应,或者都在发送数据导致缓存区溢出。所以就有了封帧(framing)的问题,即如何分割消息,使得接收方能够识别消息的开始与结束。
关于封帧,需要考虑的问题是, 接收方何时最终停止调用recv才是安全的?整个消息或数据何时才能完整无缺的传达?何时才能将接收到的消息作为一个整体来解析或处理。
适用UDP的场景:
由于TCP每次连接与断开都需要有三次握手,若有大量连接,则会产生大量的开销,在客户端与服务器之间不存在长时间连接的情况下,适用UDP更为合适,尤其是客户端太多的时候。
第二种情况: 当丢包现象发生时,如果应用程序有比简单地重传数据聪明得多的方法的话,那么就不适用TCP了。例如,如果正在进行音频通话,如果有1s的数据由于丢包而丢失了,那么只是简单地不断重新发送这1s的数据直至其成功传达是无济于事的。反之,客户端应该从传达的数据包中任意选择一些组合成一段音频(为了解决这一问题,一个智能的音频协议会用前一段音频的高度压缩版本作为数据包的开始部分,同样将其后继音频压缩,作为数据包的结束部分),然后继续进行后续操作,就好像没有发生丢包一样。如果使用TCP,那么这是不可能的,因为TCP会固执地重传丢失的信息,即使这些信息早已过时无用也不例外。UDP数据报通常是互联网实时多媒体流的基础。
参考资料:
TCP/IP网络编程 到底是什么意思 ?我理解的 TCP/IP不就是个协议麻
一,底层的编程:基于物理硬件的嵌入式系统要接入INTERNET,就必须有相应的接入程序:TCP/IP.
二,应用程序:如QQ,浏览器等需在操作系统如Windows,UNIX等下实现数据传输就需要TCP/IP编程。
关于java编程。设计一个基于TCP/IP协议的网络程序,实现如下功能:
写好了,有什么问题请追问。
客户端:
import java.net.*;
import java.io.*;
public class TestSocketClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 5566);
System.out.println("请输入计算式:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s1 = br.readLine();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream());
dos.writeUTF(s1);
dos.flush();
double s = dis.readDouble();
System.out.println("计算结果:" + s);
dis.close();
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("连接出错");
System.exit(-1);
}
}
}
服务器端:
import java.net.*;
import java.io.*;
public class TestSocketServer {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(5566);
Socket socket = ss.accept();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream());
String s = null;
if ((s = dis.readUTF()) != null) {
System.out.println("接收到的算式:" + s);
double result = 0;
String[] sarr1 = s.split("[\\+\\-\\*\\/]");
double a = Double.parseDouble(sarr1[0].trim());
double b = Double.parseDouble(sarr1[1].trim());
String[] sarr2 = s.split("^(-?\\d+)(\\.\\d+)?");
char c = sarr2[1].trim().charAt(0);
switch (c) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
result = a / b;
break;
default:
break;
}
dos.writeDouble(result);
dos.flush();
}
dis.close();
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}
TCP/IP协议与网络编程
先搞清楚 ISO/OSI与TCP/IP的关系
1.2 TCP/IP的分层体系结构与协议栈的概念
问题1:什么叫协议栈(Protocol Stack)?
如上图所示,网络协议是分层的,在这种层次结构中各层有明确的分工,不同层的协议从上到下形成了一个栈结构的依赖关系,通常将其形象地称为协议栈.问题2:为什么协议栈简称TCP/IP?
如上图所示,从该结构中可以看出,在TCP/IP的协议栈中包括很多协议(如FTP,IGMP等),但TCP和IP是该协议栈中两个最重要的协议,所以人们常常将该协议栈简称TCP/IP问题3:为什么协议栈中TCP与IP是最重要的协议?
先理解一下这4层的基本概念
------第1层:网络接口层
功能1:发包与收包
(1)发包。它是协议栈的最底层,负责将其之上的网络层要发送出去的数据(即IP数据报)发送到其下面的物理网络
(2)收包。接收由物理网络发送到该目标机的数据帧,并抽出IP数据报交给网络层。要注意,这里所说的物理网络是指各种实际传输数据的局域网或广域网等。功能2:为什么在TCP/IP协议栈中没有定义网络接口层呢?
(1)便于实现不同网络之间的互联。
实现不同网络的互联是TCP/IP要解决的最主要问题。不同的网络尽管其数据传输介质,数据传输速率等有很大的差异,但都可以实现网络内数据的传输,当然也就可以进行TCP/IP协议栈中网络层IP数据报的传输。这样TCP/IP就可以将重点放在网络之间的互联上,而不用去纠缠各种物理网络的具体实现细节,这样就非常巧妙地解决了不同类型物理网络的互联问题。这也是TCP/IP得以广泛应用的一个重要原因
(2)为将来物理网络的发展留下了广阔的空间------第2层:网际层(也称互联网络层)
功能:把源主机上的分组(在网际层传输的数据单位叫IP数据报,也称为IP分组)根据需要发送到互联网中的任何一台目标主机上.(关于怎样得到目标主机的IP地址,详见第3章中的ARP)什么叫路由选择?
在一个由很多网络组成的互联网中,一台主机(即源主机)与不在同一个网络中的另一台主机(目标主机)通信时,可能有多条通路相连,网际层的一个重要功能就是要在这些通路中做出选择,这就是所谓的路由选择功能.它是网际层一个非常重要的功能------第3层:传输层
------第4层:应用层结论:
为什么IP层非常重要?
IP层重点面向同外界打交道,比如你在广州,我在北京,IP层就能通过路由选择一条道路,以及到站后,就开始用ARP广播,你们谁是这个MAC地址的主人,听到了请回复,这时对方的IP层收包了,与自己MAC地址(全球唯一地址)一样,就开始解包(当然上层要有相应处理软件程序)
为什么TCP层非常重要?
TCP层重点面向同内部打交道,我的任务是要检查你发到我电脑里面的这个数据是不是正确的。
在IP层提供的是一种"尽力而为"的数据报传输服务,它不能保证数据总是可靠地从源主机传输到目标主机,为什么TCP能保证数据传输正确,因为它每发送一个数据都会要效验的(详见第4章传输层)
1.3 TCP/IP中数据的封装与解封过程
1.4 Internet的管理机构
例如,CNNIC(China Internet Network Information Center),中国互联网络信息中心
1.5 RFC文档
RFC(Request for Comments),至今已经发表了数千篇文章,几乎包含了与计算机通信有关的任何内容,全面地反映了Internet的研究和发展过程.==========================================
第2章 网络接口层
所讲都是硬件方面,什么是网卡,网卡是怎么做出来的,非硬件人员,跳过
==========================================
第3章 互联网络层
3.1.1 网络互联概述
internet(注意小写)---如果利用网络互联设备将两个或多个物理网络相互连接,就形成了互联网络(internetwork)
Internet(注意大写)---特指全球范围内的互联网
Router---------------将多个物理网络互联的最常用设备是路由器
Intranet----------如果一个企业内部网络,使用了Internet中的TCP/IP及其网络互联技术,但不能上网,是一个有限的,封闭的网络
Extranet----------如果一个Intranet通过防火墙等技术与外部Internet相连,则该Intranet就是一个开放的,通过外部可以访问的网络3.1.2 路由器
(1)路由器的工作原理
if(在同一IP子网) 直接发送到网络上,对方就能收到
else(不在同一IP子网) 发送一个能到达子网的路由,不知道如何传送的IP报文送给"默认网关",一级级地传送,IP报文最终送到目的地,达不到目的地的IP报文则被网络丢弃(2)路由器的功能(具有转发报文和路由选择两大功能)3.2 IP数据报格式(分报头区和数据区两大部分)
大多是理论知识,要摘抄就全摘抄了.书上介绍的才几页,也不太全,具体参考网上,此处不摘抄了,介绍几种常用网络的MTU值
注意:此节是原始套接字模块,重点.网上有教材专门讲解其模块.可以参考
----------------------------以下是总结:第1点:集中在一个点上攻,思路全围绕它转,天网恢恢,有一个漏的,当把所有注意点集中在它上时,总会找到这个程序突破处。
以上次写代码为例:在程序内找了几天BUG,一直没果,最后一个思路我叹了口气,将思路放在操作系统上,才几分钟就从微软技术支持网站上找到了,原来此问题是要改注册表问题(此程序是多线程断点下载的实例)
第2点:微软技术支持网站是个很不错的网站,里面有很多源代码,可提供一个方向
第3点:很多代码在网上是搜索不出来的,必须要相信自己,既然认为这是对的,就一定要坚持下去,各个突破
第4点:当遇上大问题时,离开电脑一段时间(例如下班后或放假),给点独立空间思考应该怎么做!