练习题|网络编程-socket开发

原文:https://www.cnblogs.com/shengyang17/p/8822745.html

1、什么是C/S架构?

  C指的是client(客户端软件),S指的是Server(服务端软件),C/S架构的软件,实现服务端软件与客户端软件基于网络通信。

2、互联网协议是什么?分别介绍五层协议中每一层的功能?

  互联网协议就是计算机界通用的语言;互联网协议分为osi七层或tcp/ip五层或tcp/ip四层;

物理层功能:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0。

数据链路层的功能:定义了电信号的分组方式按照以太网协议;一组电信号构成一个数据包,叫做一组数据‘帧’;每一数据帧分成:报头head和数据data两部分。head前六个字节和后六个字节是mac地址,基于mac地址来标示对方;在局域网内以广播的方式工作。

网络层功能:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址。

传输层功能:建立端口到端口的通信,端口即应用程序与网卡关联的编号。tcp和udp

应用层功能:有自己的协议如http、ftp协议,跑应用软件。

 

3、基于tcp协议通信,为何建立链接需要三次握手,而断开链接却需要四次挥手?

tcp协议,客户端给服务端发一次消息,服务端要回应下并且给发给客户端,然后客户端再发给服务端,中间两步回应下+给客户端发消息可以合成一步,链接建立完成也就是三次握手;客户端说要断开链接PIN=1,服务端确认下ack=1,客户端接收到了,这条管道就断开了,服务端要断开发PIN=1,客户端回一个ack=1,管道就断开了。

客户端说把数据传完了,服务端不一定传完数据了,中间那两步不能合成一步,所以断开链接需要四次挥手。

4、为何基于tcp协议的通信比基于udp协议的通信更可靠?

   tcp协议一定是先建好双向链接,发一个数据包要得到确认才算发送完成,没有收到就一直给你重发;udp协议没有链接存在,udp直接丢数据,不管你有没有收到。

 

5、‍流式协议指的是什么协议,数据报协议指的是什么协议?

  流式协议指的是tcp协议,数据报协议指的是udp协议

 

6、什么是socket?简述基于tcp协议的套接字通信流程 

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部。 

 服务端先初始化Socket实例化一个类拿到对象(才能调用下面的接口),然后绑定IP端口(bind),监听(listen)就是说客户端可以来连我了,调用accept接收链接;这时客户端初始化一个socket,然后connect与服务端建立好双向链接与accept对应。客户端发送请求数据,服务端处理请求并给客户端回应数据,这样一个通信循环;最后关闭套接字,一次交互结束。

 

7、什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?

 如客户端只recv(1024), 可结果比1024长那怎么办,只好在服务器端的IO缓冲区里把客户端还没收走的暂时存下来,等客户端下次再来收,所以当客户端第2次调用recv(1024)就会首先把上次没收完的数据先收下来,再收df命令的结果。

这个现象叫做粘包,就是指两次结果粘到一起了。它的发生主要是因为socket缓冲区导致的。

所谓粘包问题原因:(1)主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。(2)发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。

发生粘包的情况:(1)发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)(2)接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

 

8、基于socket开发一个聊天程序,实现两端互相发送和接收消息

server

复制代码
#Author:Kris# import socket
#
# HOST = ''                 # Symbolic name meaning all available interfaces
# PORT = 50007              # Arbitrary non-privileged port
#
# sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # sock_server.bind((HOST, PORT)) # # sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝 # conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 # # with conn: # print('Connected by', addr) # while True: # data = conn.recv(1024) #接收1024个字节 # print("server recv:",conn.getpeername(), data.decode()) # if not data: break #收不到数据,就break # conn.sendall(data) #把收到的数据再全部返回给客户端 import socket HOST = '' # Symbolic name meaning all available interfaces PORT = 50007 # Arbitrary non-privileged port sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_server.bind((HOST, PORT)) sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝 conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 with conn: print('Connected by', addr) while True: data = conn.recv(1024) #接收1024个字节 print("recv from Alex:",conn.getpeername(), data.decode()) if not data: break #收不到数据,就break response = input(">>>").strip() conn.send(response.encode()) print("send to alex:",response)
复制代码

client

复制代码
#Author:Krisimport socketHOST = 'localhost'    # The remote host
PORT = 50007 # The same port as used by the server client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) while True: msg = input(">>>:").strip() if len(msg) == 0:continue client.sendall(msg.encode()) #发送用户输入的数据,必须是bytes模式 data = client.recv(1024) print('Received',data.decode()) #收到服务器的响应后,decode一下
复制代码

   

9、基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果

 server

复制代码
import socket
import subprocessphone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',9901)) #0-65535:0-1024给操作系统使用 phone.listen(5) print('starting...') while True: # 链接循环 conn,client_addr=phone.accept() print(client_addr) while True: #通信循环 try: #1、收命令 cmd=conn.recv(1024) if not cmd:break #适用于linux操作系统 #2、执行命令,拿到结果 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=obj.stdout.read() #它就是bytes格式;正确的 stderr=obj.stderr.read() #错误的结果 #3、把命令的结果返回给客户端 print(len(stdout)+len(stderr)) conn.send(stdout+stderr) #+是一个可以优化的点,申请一个新的内存空间 except ConnectionResetError: #适用于windows操作系统 break conn.close() phone.close()
复制代码

client

复制代码
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',9901)) while True: #1、发命令 cmd=input('>>: ').strip() #ls /etc if not cmd:continue phone.send(cmd.encode('utf-8')) #2、拿命令的结果,并打印 data=phone.recv(1024) #1024是一个坑 print(data.decode('gbk')) phone.close()
复制代码

 

10、基于tcp协议编写简单FTP程序,实现上传、下载文件功能,并解决粘包问题

 服务端

复制代码
import socket
import struct
import json
import subprocess
import osclass MYTCPServer:address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 server_dir='file_upload' def __init__(self, server_address, bind_and_activate=True): """Constructor. May be extended, do not override.""" self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise def server_bind(self): """Called by constructor to bind the socket. """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() def server_activate(self): """Called by constructor to activate the server. """  self.socket.listen(self.request_queue_size) def server_close(self): """Called to clean-up the server. """  self.socket.close() def get_request(self): """Get the request and client address from the socket. """ return self.socket.accept() def close_request(self, request): """Called to clean up an individual request.""" request.close() def run(self): while True: self.conn,self.client_addr=self.get_request() print('from client ',self.client_addr) while True: try: head_struct = self.conn.recv(4) if not head_struct:break head_len = struct.unpack('i', head_struct)[0] head_json = self.conn.recv(head_len).decode(self.coding) head_dic = json.loads(head_json) print(head_dic) #head_dic={'cmd':'put','filename':'a.txt','filesize':123123} cmd=head_dic['cmd'] if hasattr(self,cmd): func=getattr(self,cmd) func(head_dic) except Exception: break def put(self,args): file_path=os.path.normpath(os.path.join( self.server_dir, args['filename'] )) filesize=args['filesize'] recv_size=0 print('----->',file_path) with open(file_path,'wb') as f: while recv_size < filesize: recv_data=self.conn.recv(self.max_packet_size) f.write(recv_data) recv_size+=len(recv_data) print('recvsize:%s filesize:%s' %(recv_size,filesize)) tcpserver1=MYTCPServer(('127.0.0.1',8080)) tcpserver1.run()
复制代码

客户端

复制代码
import socket
import struct
import json
import osclass MYTCPClient:address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 def __init__(self, server_address, connect=True): self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if connect: try: self.client_connect() except: self.client_close() raise def client_connect(self): self.socket.connect(self.server_address) def client_close(self): self.socket.close() def run(self): while True: inp=input(">>: ").strip() if not inp:continue l=inp.split() cmd=l[0] if hasattr(self,cmd): func=getattr(self,cmd) func(l) def put(self,args): cmd=args[0] filename=args[1] if not os.path.isfile(filename): print('file:%s is not exists' %filename) return else: filesize=os.path.getsize(filename) head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize} print(head_dic) head_json=json.dumps(head_dic) head_json_bytes=bytes(head_json,encoding=self.coding) head_struct=struct.pack('i',len(head_json_bytes)) self.socket.send(head_struct) self.socket.send(head_json_bytes) send_size=0 with open(filename,'rb') as f: for line in f: self.socket.send(line) send_size+=len(line) print(send_size) else: print('upload successful') client=MYTCPClient(('127.0.0.1',8080)) client.run()
复制代码

 

 

11、基于udp协议编写程序,实现功能

  1. 执行指定的命令,让客户端可以查看服务端的时间

  2. 执行指定的命令,让客户端可以与服务的的时间同步

 server

复制代码
import socket
import subprocess
import timeserver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080)) while True: data, client_addr = server.recvfrom(1024) print(data, client_addr) obj = subprocess.Popen(data.decode('utf-8'),shell=True, # time 命令在windows 下不能用 stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() print(stdout+stderr) server.sendto(stdout+stderr,client_addr) if data.decode('utf-8') == 'time': str_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # str_time = '2017-01-01 00:00:00' server.sendto(str_time.encode('gbk'), client_addr) server.close()
复制代码

client

复制代码
import socket
import os
import time
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:msg = input('>>>:').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) data,server_addr = client.recvfrom(1024) print(data.decode('utf-8'),server_addr) localtime = time.localtime() os.system("date %d-%d-%d" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday)) # 设置日期 os.system("time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec)) # 设置时间 client.close()
复制代码

 

分类: 练习

转载于:https://www.cnblogs.com/fmgao-technology/p/9150284.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

okhttputils java_Java OkHttpUtils.post方法代码示例

import com.zhy.http.okhttp.OkHttpUtils; //导入方法依赖的package包/类Overridepublic void performRequestAsync(AyoRequest request, BaseResponseDispatcher responseHandler, BaseHttpCallback callback) {String url request.url;//基于OkHttpUtils辅助类//1 method决定…

近日安排

先把二分题做了&#xff0c;二分哪个小白书学了。 做图论题&#xff0c;4道转载于:https://www.cnblogs.com/no-regrets/p/7215366.html

ABP vNext微服务架构详细教程(补充篇)——单层模板(上)

简介在之前的《ABP vNext微服务架构详细教程》系列中&#xff0c;我们已经构建了完整的微服务架构实例&#xff0c;但是在开发过程中&#xff0c;我们会发现每个基础服务都包含10个类库&#xff0c;这是给予DDD四层架构下ABP的实现方案&#xff0c;但是实际使用中我们会发现&am…

JQuery this和$(this)的区别及获取$(this)子元素对象的方法

1.JQuery this和$(this)的区别 // this其实是一个Html 元素。 // $this 只是个变量名&#xff0c;加$是为说明其是个jquery对象。 // 而$(this)是个转换&#xff0c;将this表示的dom对象转为jquery对象&#xff0c;这样就可以使用jquery提供的方法操作。 相信很多刚接触JQuery的…

mybatis源码学习(三):MappedStatement的解析过程

我们之前介绍过MappedStatement表示的是XML中的一个SQL。类当中的很多字段都是SQL中对应的属性。我们先来了解一下这个类的属性&#xff1a; public final class MappedStatement {private String resource;private Configuration configuration;//sql的IDprivate String id;//…

sealed java_Java包isSealed()方法与示例

包类isSealed()方法isSealed()方法在java.lang包中可用。isSealed()方法用于检查此程序包是否密封。isSealed()方法是一种非静态方法&#xff0c;只能通过类对象访问&#xff0c;如果尝试使用类名称访问该方法&#xff0c;则会收到错误消息。isSealed()方法在密封包装时不会引发…

java enum分析

用法一&#xff1a;常量 在JDK1.5 之前&#xff0c;我们定义常量都是&#xff1a; public static fianl.... 。现在好了&#xff0c;有了枚举&#xff0c;可以把相关的常量分组到一个枚举类型里&#xff0c;而且枚举提供了比常量更多的方法。 public enum Color { RED, GREEN,…

1176: C语言实验题――数组逆序

描述:输入10个整数存入一维数组&#xff0c;再按逆序重新存放后再输出。输入:输入包括一行。 10个以空格格开的整数输出:逆序的10个整数&#xff0c;整数以空格格开样例输入:1 3 5 9 7 6 8 2 4 0样例输出:0 4 2 8 6 7 9 5 3 1考点:数的交换代码: #include <stdio.h> int …

C# 二十年语法变迁之 C# 8参考

C# 二十年语法变迁之 C# 8参考自从 C# 于 2000 年推出以来&#xff0c;该语言的规模已经大大增加&#xff0c;我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此&#xff0c;我想写一系列快速参考文章&#xff0c;总结自 C# 2.0 以来所有主要的新语言…

windows 提权 cve-2018-8897

windows 提权 cve-2018-8897影响范围&#xff1a;基本上是全版本具体影响范围看详情&#xff1a;https://portal.msrc.microsoft.co … isory/CVE-2018-8897http://www.o2oxy.cn/wp-content/uploads/2018/06/cve-2018-8897.rar转载于:https://blog.51cto.com/9861015/2126608

java servlet练习测试

步骤&#xff1a; 0、首先创建web project&#xff0c;工程名&#xff1a;test_servlet 1、编写Servlet&#xff0c;TestServlet.java文件内容&#xff1a; package com.ouyang.servlet;import java.io.IOException; import java.sql.Connection; import java.sql.DriverManage…

java 检测ip网速_java心跳测网速Demo

//心跳中可以放//自己瞎搞的&#xff0c;有人帮改进吗&#xff1f;package netTest;import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;public class net_test_one {public static void main(String[] args) {try {String[] cmd ne…

简洁的 Bash Programming 技巧(三)

这是简洁的 Bash Programming 技巧系列的第三篇文章&#xff0c;这一系列的文章专门介绍 Bash 编程中一些简洁的技巧&#xff0c;帮助大家提高平时 Bash 编程的效率。有兴趣的同学可以回顾下之前的两篇文章&#xff08;一&#xff09;和续篇。 1. 替换语法${parameter/pattern/…

《ASP.NET Core 6框架揭秘》实例演示[19]:数据加解密与哈希

数据保护&#xff08;Data Protection&#xff09;框架旨在解决数据在传输与持久化存储过程中的一致性&#xff08;Integrity&#xff09;和机密性&#xff08;confidentiality&#xff09;问题&#xff0c;前者用于检验接收到的数据是否经过篡改&#xff0c;后者通过对原始的数…

java开发保险案例_Java实现双保险线程的示例代码

双保险线程&#xff0c;每次启动2个相同的线程&#xff0c;互相检测&#xff0c;避免线程死锁造成影响。两个线程都运行&#xff0c;但只有一个线程执行业务&#xff0c;但都会检测对方的时间戳 如果时间戳超过休眠时间3倍没有更新的话&#xff0c;则重新启动对方线程。例子&am…

如何在ABAP Netweaver和CloudFoundry里记录并查看日志

Netweaver 要记录日志需要有一个checkpoint group&#xff0c;可以自行创建也可以使用标准的。这里我重用标准的group&#xff1a;DEMO_CHECKPOINT_GROUP。 tcode SAAB&#xff0c;点Display <->Activate进入编辑模式&#xff0c;将Logpoints设置为"Log"&#…

TiDB 源码初探

作者: 申砾 本文档面向 TiDB 社区开发者&#xff0c;主要介绍 TiDB 的系统架构、代码结构以及执行流程。 目的是使得开发者阅读文档后&#xff0c;可以对 TiDB 项目有一个整体的了解&#xff0c;更好的参与进来。首先会介绍一下大体的结构以及 Golang 包的结构&#xff0c;然后…

C#高性能低GC 非托管动态扩容数组

开始之前相比固定长度的Array&#xff0c;大家可能在编程的时候经常会使用List<T>&#xff0c;同时可能会经常往里面Add东西&#xff0c;因为List具有可扩容性&#xff0c;但是注重GC的朋友会发现&#xff08;比如Unity开发者&#xff09;&#xff0c;List.Resize会造成扩…

leetCode 53. maximum subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [-2,1,-3,4,-1,2,1,-5,4],the contiguous subarray [4,-1,2,1] has the largest sum 6. 贪婪算法找每个当前位置对应的最大的subar…

如何成为有效学习的高手(许岑)——思维导图

总结自许岑精品课《如何成为有效学习的高手》&#xff0c;图片看不清的可以看下面。 最后有彩蛋&#xff01;最后有彩蛋&#xff01;最后有彩蛋&#xff01; 定义 高效学习的定义&#xff1a;找到最适合自己的学习手法&#xff0c;在相对短的时间内集中注意力&#xff0c;以解决…