HNU计网实验:实验二 网络基础编程实验(JAVA\Python3)

说些什么

记得当时做实验的时候我是满心的卧槽的,因为实验一和实验二简直是天壤之别,我记得在验收前的那个下午,我依然在疯狂改代码。

众所周知,我是一个衷心于摸鱼的小菜鸡,所以我这个代码其实是我在别人代码的基础上改出来的一个,其实理论上我应该bia出来参考的博客的网址的,但是这是好早之前的了我找不到了…

实验目的

通过本实验,学习采用Socket(套接字)设计简单的网络数据收发程序,理解应用数据包是如何通过传输层进行传送的。

实验内容

Socket(套接字)是一种抽象层,应用程序通过它来发送和接收数据,就像应用程序打开一个文件句柄,将数据读写到稳定的存储器上一样。一个socket允许应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行通信。一台计算机上的应用程序向socket写入的信息能够被另一台计算机上的另一个应用程序读取,反之亦然。
不同类型的socket与不同类型的底层协议族以及同一协议族中的不同协议栈相关联。现在TCP/IP协议族中的主要socket类型为流套接字(sockets sockets)和数据报套接字(datagram sockets)。流套接字将TCP作为其端对端协议(底层使用IP协议),提供了一个可信赖的字节流服务。一个TCP/IP流套接字代表了TCP连接的一端。数据报套接字使用UDP协议(底层同样使用IP协议),提供了一个"尽力而为"(best-effort)的数据报服务,应用程序可以通过它发送最长65500字节的个人信息。一个TCP/IP套接字由一个互联网地址,一个端对端协议(TCP或UDP协议)以及一个端口号唯一确定。

写一个简单的chat程序,并能互传文件,编程语言不限

客户端

#客户端的chat

import socket
import sys
import os

ip_port = ('127.0.0.1',9998) #使用9999会提示被占用?
sk = socket.socket()
sk.connect(ip_port)
container = {'key':'','data':''} #文件路径的剪切
while True:
    FLAG = input('0.接收文件 1.发送文件 2.进行消息发送\n')
    sk.sendall(str(FLAG).encode('utf-8'))

    if FLAG=='1': #发送文件,即原本的功能
        path = input('path:') # 客户端输入要上传文件的路径 
        path = 'F:\\\\'+path #F盘的test10031.txt
        print('哈哈哈哈哈',path) ##################test
        file_name = os.path.basename(path) # 根据路径获取文件名
        file_size=os.stat(path).st_size # 获取文件大小
        Informf=(file_name+'|'+str(file_size)) #客户端的打包
        sk.send(Informf.encode()) # 发送文件名 和 文件大小
        # 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
        msg=sk.recv(1024)
        print(msg.decode())

        send_size = 0
        f= open(path,'rb')
        Flag = True
        while Flag:
            if send_size + 1024 >file_size:
                data = f.read(file_size-send_size)
                Flag = False
            else:
                data = f.read(1024)
                send_size+=1024
            sk.send(data)

        aaa = sk.recv(1024) #新增接收
        print(aaa.decode())

        f.close()

    elif FLAG=='0' : #接收
        message=sk.recv(1024)
        print(message.decode(encoding='utf8'))

        message = input('path: ')
        message = str(message)
        # 发送数据 加码
        sk.sendall(message.encode('utf-8'))
        print('客户端等待...')

        #之前的Srv
        pre_data = sk.recv(1024).decode()
        #获取请求方法、文件名、文件大小
        file_name,file_size = pre_data.split('|') #服务器的解包
        # 防止粘包,给客户端发送一个信号。
        sk.sendall('收到'.encode())            
        #已经接收文件的大小
        recv_size = 0
        file_dir = os.path.join('F:\\\\',message) #下载文件路径拼接 ####理论上没错的样子
        print('嘿嘿嘿嘿嘿',file_dir)
        f = open(file_dir,'wb')
        Flag = True
        while Flag:
            #未上传完毕,
            if int(file_size)>recv_size:
                #最多接收1024,可能接收的小于1024
                data = sk.recv(1024) 
                recv_size+=len(data)
                #写入文件
                f.write(data)
            #上传完毕,则退出循环
            else:
                recv_size = 0
                Flag = False

        sk.sendall('下载完成'.encode()) #新增发送
                
        print('接收成功')
        f.close()
        #Srv至此

    else : #进行信息发送
        print('开始进行聊天')

        while True:
            msg = input("> ")
            if msg == 'stop':
                sk.send('stop'.encode('utf-8')) #客户端发送停止消息
                break
            elif not msg:
                continue
            sk.send(msg.encode('utf-8'))  # 客户端发送消息

            rev_data = sk.recv(1024)  # 客户端接受消息
            if not rev_data:
                break

            print('服务器消息:', rev_data.decode('utf-8'))


sk.close()

服务端

#服务端
import socketserver
import os

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        print ('connected...')
        while True:

            order = conn.recv(1024).decode(encoding='utf8') #增加读取
            print('执行',order)

            if order == '1' : #接收文件,即原本的任务

                print('服务器等待...')

                pre_data = conn.recv(1024).decode()
                #获取请求方法、文件名、文件大小
                file_name,file_size = pre_data.split('|') #服务器的解包
                # 防止粘包,给客户端发送一个信号。
                conn.sendall('收到'.encode())            
                #已经接收文件的大小
                recv_size = 0
                file_dir = os.path.join('D:\\\\',file_name) #接收的文件路径拼接 #现在没错了

                print("啦啦啦啦啦",file_dir) #####test

                f = open(file_dir,'wb')
                Flag = True
                while Flag:
                    #未上传完毕,
                    if int(file_size)>recv_size:
                       #最多接收1024,可能接收的小于1024
                        data = conn.recv(1024) 
                        recv_size+=len(data)
                        #写入文件
                        f.write(data)
                    #上传完毕,则退出循环
                    else:
                        recv_size = 0
                        Flag = False

                conn.sendall('下载完成'.encode()) #添加发送

                print('上传成功')
                f.close()
        
            if order == '0' : #发送文件
                conn.sendall('服务器准备发送文件'.encode('utf-8'))

                #原来的Clt
                #path = input('path:') # 客户端输入要上传文件的路径
                path = conn.recv(1024).decode() #这里路径是从客户端读取的
                #file_name = os.path.basename(path) # 根据路径获取文件名
                file_name = os.path.join('D:\\\\', path) #拼接 ###########理论上没错
                print('耶耶耶耶耶',file_name)
                file_size=os.stat(file_name).st_size # 获取文件大小
                Informf=(file_name+'|'+str(file_size)) # 包装文件名 和 文件大小
                conn.send(Informf.encode()) # 发送
                # 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
                bbb=conn.recv(1024).decode()
                print(bbb)

                send_size = 0
                f= open(file_name,'rb')
                Flag = True
                while Flag:
                    if send_size + 1024 >file_size:
                        data = f.read(file_size-send_size)
                        Flag = False
                    else:
                        data = f.read(1024)
                        send_size+=1024
                    conn.send(data)

                conn.recv(1024) #新增接收
                f.close()

            if order == '2' :
                print('开始进行聊天')
                while True:
                    data = conn.recv(1024)  # 接受客户端发送的消息
                    print('客户端消息:', data.decode('utf-8'))
                    if not data:
                        continue
                    elif data.decode() == 'stop':
                        print('停止聊天')
                        break
                    message = input('> ')

                    conn.send(message.encode('utf-8'))  # 客户端发送消息
    
instance = socketserver.ThreadingTCPServer(('127.0.0.1',9998),MyServer)
instance.serve_forever()

主要思路就是通过FLAG的值来判断操作:
FLAG=='1’的时候就是发送文件
FLAG=='0’的时候就是接收文件
FLAG=='2’的时候就是信息互发

有些奇奇怪怪的输出不需要在意,当时有bug然后de不出来,就想着通过输出来看在哪一步执行不来…
朴素的程序员往往用最质朴的方法来debug…
我真的会谢…

你可能感兴趣的:(计网,网络,java,tcp/ip)