用scala实现一个基于TCP Socket的快速文件传输程序

这是用scala实现的一个简单的文件传输程序。

服务端

package jpush

import java.io.{DataInputStream, File, FileOutputStream}
import java.net.ServerSocket

import scala.collection.JavaConversions._

/**
  * Created by dingb on 2016/6/3.
  */
object Server extends  App {
  def port = 8899
  override def main(args: Array[String]) {
    val roots = args.toList match {
      case Nil => List(new File(System.getProperty("user.dir")))
      case _ =>  args.map(new File(_)).toList
    }

    printf("dst root is %s\n", roots.mkString(","))
    val ss = new ServerSocket(port)
    def accept: Unit = {
      val s = ss.accept()
      printf("%s in \n", s.getRemoteSocketAddress);
      async {
        val dis = new DataInputStream(s.getInputStream)
        val fn = dis.readUTF
        val size = dis.readLong
        printf("loading %s %d\n", fn, size);
        if(size > 0) {
          roots.foreach(new File(_, fn).getParentFile.mkdirs())
          val oses = roots.map(new File(_, fn)).map(new FileOutputStream(_))
          val buf = new Array[Byte](1024)
          var done = false
          while(!done) {
            val r = dis.read(buf)
            if(r <= 0) done = true
            else oses.foreach(_.write(buf, 0, r))
          }
          oses.foreach(_.close)
        }
      }
      accept
    }
    accept
  }

  def async(body : => Unit) = {
    val t = new Thread(new Runnable {
      override def run(): Unit = {
        body
      }
    })
    t.start()
  }
}

客户端

package jpush

import java.io.{DataOutputStream, File, FileInputStream}
import java.net.Socket

/**
  * Created by dingb on 2016/6/3.
  */
object Client  extends  App{

  def send_file(ip: String, file: File, top: String): Unit = {
    val fis = new FileInputStream(file)
    val s = new Socket(ip, Server.port)
    val dos = new DataOutputStream(s.getOutputStream)
    val remotename = top + File.separator + file.getName
    printf("sending %d bytes %s to %s\n", file.length(), file.getAbsolutePath, remotename)
    dos.writeUTF(remotename)
    dos.writeLong(file.length())
    val buf = new Array[Byte](1024)
    var done = false
    while(!done) {
      val r = fis.read(buf)
      if(r <= 0) done = true
      else dos.write(buf, 0, r)
    }
    dos.close()
    fis.close()
    s.close()

  }

  def send(ip: String, file: File, top: String): Unit = {
    if(file.isDirectory) file.listFiles().foreach(send(ip, _, "" + File.separator + file.getName))
    else send_file(ip, file, top)

  }

  override def main(args: Array[String]) {
    if(args.length < 1)  usage()
    else args.drop(1).map(new File(_)).foreach(send(args(0), _, ""))

  }

  def usage(): Unit = {
    println("usage: jpsh.Client <ip> [file]...")
    System.exit(-1)
  }
}

源代码下载

https://github.com/dingbig/jpush

时间: 2024-08-06 12:21:50

用scala实现一个基于TCP Socket的快速文件传输程序的相关文章

Windows下基于TCP协议的大文件传输(流形式)

简单实现TCP下的大文件高效传输 在TCP下进行大文件传输,不像小文件那样直接打包个BUFFER发送出去,因为文件比较大可能是1G,2G或更大,第一效率问题,第二TCP粘包问题.针对服务端的设计来说就更需要严紧些.下面介绍简单地实现大文件在TCP的传输应用. 粘包出现原因:在流传输中出现,UDP不会出现粘包,因为它有消息边界(参考Windows 网络编程) 1 发送端需要等缓冲区满才发送出去,造成粘包 2 接收方不及时接收缓冲区的包,造成多个包接收 解决办法: 为了避免粘包现象,可采取以下几种措

[C++基础]一个比较常用的配置文件/初始化文件读取程序

在编程中,我们经常会遇到一些配置文件或初始化文件.这些文件通常后缀名为.ini或者.conf,可以直接用记事本打开.里面会存储一些程序参数,在程序中直接读取使用.例如,计算机与服务器通信,服务器的ip地址,段口号可以存储于ini文件中.这样如果我想换另外一台服务器时,直接将ini文件中的ip地址改变即可,程序源代码不需要做任何修改. 本文将分享一段常用代码,用于读取配置文件中的信息.本文中的代码为C语言编写,在ubuntu 12.04 linux系统中调试没有问题.具体操作如下: 1. 首先用记

小白基于Csocket的局域网聊天文件传输软件C/S模式

首先,并不建议大家用Csocket,经验之谈,CAsyncSocket基础上派生的一个同步阻塞Socket的封装类,也就是说编程的过程很多麻烦,但是我坚持下来了.....好烦.... .................................................分割线..................................................................................... 思想其实很容易理解,S(服务器端)创建s

一个基于TCP/IP的小项目,实现广播消息的功能。(超详细版)

1.结合现状 功能分析 该功能基于上个项目的改进,主要是通过对服务器端代码的修改,以及对客户端作少许修改,实现开启多客户端时,一个客户端发送消息,达到对所有客户端广播的效果.可参考网吧里的点歌系统,比如某某用户在网吧点了一首歌,其他用户电脑的左下角都会弹出一个某某用户点了一首七里香,或者游戏里面的频道聊天,每个人发完消息后,聊天室里的人都知道你发的消息了,就像下图一样,这也正是做这个功能的初衷吧. 2.图说代码 代码细说: 服务器里面定义了两个字段,一个用于服务器与客户端的连接,另一个目的在于做

一个基于TCP/IP的服务器与客户端通讯的小项目(超详细版)

1.目的:实现客户端向服务器发送数据 原理: 2.建立两个控制台应用,一个为服务器,用于接收数据.一个为客户端,用于发送数据. 关键类与对应方法: 1)类IPEndPoint: 1.是抽象类EndPoint的实现类 2.Socket对象的RemoteEndPoint. LocalEndPoint都是这个类型 3.属性Address: 使用IPv4表示的地址 4.属性Port:使用int表示的端口 2)类Socket: 这个类即可以用于作服务器端的开发,又可以作客户端的开发 构造方法: 参数 Ad

c++下基于windows socket的单线程服务器客户端程序

今天自己用编写了一个简单的c++服务器客户端程序,注释较详细,在此做个笔记. windows下socket编程的主要流程可概括如下:初始化ws2_32.dll动态库-->创建套接字-->绑定地址信息-->服务器进行监听/客户端连接服务器-->数据交换-->关闭套接字对象. 服务器端: 1 #include <Winsock2.h> 2 #include <Ws2tcpip.h> 3 #include <iostream> 4 5 #prag

基于TCP协议的java单线程通信程序

这是大二学JAVA基础时写的一个小程序,通过在程序中设置主机IP和端口实现两台主机间的通信.由于当时对JAVA编程的规范掌握的不是很好, 所以程序界面设计代码和通信模块代码都放在了同一个类中. 类一:服务器端的代码 import java.awt.BorderLayout;import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.B

Scala 获取一个url的内容存到本地文件

1, 下载有效url的内容 /** * 获取一个有效的url地址的内容存到本地的本件中 * @param url * @param file */ def downloadUrlFile(url: String, file: String) = { val pw = new PrintWriter(file) pw.write(Source.fromURL(url, "utf-8").mkString) }

【原创】一个基于简单剪枝的DFS解数独程序

问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empty cells are indicated by the character *.*. You may assume that there will be only one unique solution. 问题链接: https://oj.leetcode.com/problems/sudoku-