*/

.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}

.hljs-comment,
.hljs-template_comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}

.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.javascript .hljs-title,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}

.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #099;
}

.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.tex .hljs-formula {
color: #d14;
}

.hljs-title,
.hljs-id,
.coffeescript .hljs-params,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}

.javascript .hljs-title,
.lisp .hljs-title,
.clojure .hljs-title,
.hljs-subst {
font-weight: normal;
}

.hljs-class .hljs-title,
.haskell .hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}

.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}

.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
color: #008080;
}

.hljs-regexp {
color: #009926;
}

.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}

.hljs-built_in,
.lisp .hljs-title,
.clojure .hljs-built_in {
color: #0086b3;
}

.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}

.hljs-deletion {
background: #fdd;
}

.hljs-addition {
background: #dfd;
}

.diff .hljs-change {
background: #0086b3;
}

.hljs-chunk {
color: #aaa;
}

#container {
padding: 15px;
}
pre {
border: 1px solid #ccc;
border-radius: 4px;
display: block;
background-color: #f8f8f8;
}
pre code {
white-space: pre-wrap;
}
.hljs,
code {
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
}
:not(pre) > code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
white-space: nowrap;
border-radius: 4px;
}
-->

TCP通信需要明确的几点:

  1. tcp通信是面向连接的,需要先启动服务端,再启动客户端。
  2. 客户端和服务端都要创建套接字对象,客户端需要指定服务端套接字(ip+port),而服务端必须指定服务端口。
    Socket client_socket = new Socket("192.168.100.17",8888); //客户端套接字(Socket类的套接字为已连接套接字)
    ServerSocket listen_socket = new ServerSocket(8888); //服务端套接字,此时为监听套接字(已经bind()地址和端口了)
  3. 服务端需要使用accept()方法将监听套接字转变为已连接套接字。这个监听套接字可以生成多个已连接套接字,这样连接后还能监听其他客户端的请求。因此,这里应该使用多线程实现并发访问。获得了已连接套接字,就可以获取很多客户端的信息,例如客户端的ip地址,发送请求的端口等。

    Socket server_scoket = socket.accept();
    Socket server_scoket2 = socket.accept();
    Socket server_scoket3 = socket.accept();

    服务端要实现并发连接,大致使用如下代码:其中ThreadTask是线程任务对象。

    public static void main(String[] args) throws IOException {
    ServerSocket listen_sock = new ServerSocket(8888); //监听套接字只需创建一个,因此在任务之外 while (true) { //每建立一个连接,就开启一个线程
    Socket conn_sock = listen_sock.accept(); //没有新连接进来时,main主线程阻塞在此
    new Thread(new ThreadTask(conn_sock)).start();
    }
    }
  4. 客户端需要根据已连接套接字获取输出流,服务端需要根据套接字获取输入流。当然,既然有了已连接套接字,那么获取无论哪一端都可以获取到输入流、输出流。
    OutputStream send_stream = client_socket.getOutputStream();   //客户端获取输出流
    InputStream recv_stream = server_socket.getInputStream();
  5. 服务端应主动关闭已连接套接字,至于监听套接字则在合适的地方关闭。
  6. 服务端应该循环不断地负责接收。

简单的Client端:

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket; public class TCPClient { public static void main(String[] args) {
// 1.创建客户端套接字
Socket c_sock = null;
OutputStream client_outstream = null;
try {
c_sock = new Socket("192.168.0.124",8888); // 2.获取输出流
client_outstream = c_sock.getOutputStream(); // 3.输出数据
client_outstream.write("Hello,i'm coming".getBytes()); } catch (IOException e) {
e.printStackTrace();
} finally {
if(c_sock != null){
try{
c_sock.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
}
}

简单的Server端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket; public class TCPServer { public static void main(String[] args) { // 1.创建监听套接字
ServerSocket listen_sock = null;
try {
listen_sock = new ServerSocket(8888); } catch(IOException i) {
i.printStackTrace();
} Socket server_sock = null;
InputStream in_sock = null;
while (true) {
try {
// 2.和客户端建立连接,生成已连接套接字,并获取客户端ip地址
server_sock = listen_sock.accept();
String client_ip = server_sock.getInetAddress().getHostAddress();
System.out.println("Client: " + client_ip + " connected"); // 3.根据已连接套接字,获取输入流,读取客户端发送的数据
in_sock = server_sock.getInputStream();
BufferedReader bufr = new BufferedReader(new InputStreamReader(in_sock));
String line = null;
while ((line = bufr.readLine()) != null) {
System.out.println(line);
} // 4.关闭已连接套接字
server_sock.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

以下是tcp实现文件上传功能:

  1. 客户端除了套接字的输出流,还有读取本地文件的输入流,还有套接字的输入流来读取来自服务端的反馈信息。
  2. 服务端也同样有三流:套接字的输入、输出流,写入上传目标文件的输出流。
  3. 客户端读取本地文件的所有数据后,需要使用套接字的shutdownOutput()来通知服务端套接字的输出流已到末尾。
  4. 服务端为了能为多人提供上传功能,需要使用多线程实现并发连接。

Client端:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket; public class UploadClient { public static void main(String[] args) {
// TODO Auto-generated method stub
String server_addr = "192.168.0.124";
int server_port = 8888; Socket send_sock = null;
FileInputStream local_read = null;
try {
// 1.客户端套接字
send_sock = new Socket(server_addr, server_port); // 2.获取连接管道的输出流
OutputStream send_stream = send_sock.getOutputStream(); // 3.字节输入流读取本地文件数据,并使用套接字的输出流发送出去
local_read = new FileInputStream("d:/myjava/net/SQL.docx"); byte[] buf = new byte[1024];
int len = 0;
while ((len = local_read.read(buf)) != -1) {
send_stream.write(buf, 0, len);
} // 4.标记输出流到结尾
send_sock.shutdownOutput(); // 5.接收服务端的反馈数据,如上传成功,上传失败等
InputStream recv_stream = send_sock.getInputStream();
BufferedReader ack_recv = new BufferedReader(new InputStreamReader(recv_stream));
String line = null;
while ((line = ack_recv.readLine()) != null) {
System.out.println(line);
} } catch (IOException i) {
i.printStackTrace();
} finally {
if (send_sock != null) {
try {
send_sock.close();
local_read.close();
} catch (IOException i1) {
i1.printStackTrace();
}
} if (local_read != null) {
try {
local_read.close();
} catch (IOException i2) {
i2.printStackTrace();
}
}
}
}
}

Server端:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket; public class UploadServer {
public static void main(String[] args) throws IOException {
ServerSocket listen_sock = new ServerSocket(8888); //监听套接字只需创建一个,因此在任务之外 while (true) { //每建立一个连接,就开启一个线程
Socket conn_sock = listen_sock.accept(); //没有新连接进来时,main主线程阻塞在此
new Thread(new Uploader(conn_sock)).start();
}
}
} class Uploader implements Runnable {
private File dest_dir = new File("d:/temp"); // 上传目录
private Socket conn_sock = null; // 连接套接字
InputStream recv_stream = null;
FileOutputStream dest_stream = null; Uploader(Socket conn_sock) throws IOException {
this.conn_sock = conn_sock;
} public void run() {
try {
if (!dest_dir.exists()) {
dest_dir.mkdirs();
}
// 1.获取连接管道的输入流
recv_stream = conn_sock.getInputStream(); // 客户端ip
String client_ip = conn_sock.getInetAddress().getHostAddress();
System.out.println(client_ip + ".....connected"); // 2.文件的上传位置,即输出目标,以ip命名。如果文件已存在,则使用括号加数字新建文件,如"192.168.100.23(1).txt"
File dest_file = new File(dest_dir, client_ip + ".docx");
int count = 1;
while (dest_file.exists()) {
dest_file = new File(dest_dir, client_ip + "(" + count + ")" + ".docx");
count++;
} // 3.读取数据并写入目标文件
dest_stream = new FileOutputStream(dest_file);
byte[] buf = new byte[1024];
int len = 0;
while ((len = recv_stream.read(buf)) != -1) {
dest_stream.write(buf, 0, len);
} // 4. 向客户端反馈信息
OutputStream ack_send = conn_sock.getOutputStream();
byte[] text = "upload successful!".getBytes();
ack_send.write(text); } catch (IOException e1) {
e1.printStackTrace();
} finally {
if (dest_stream != null) {
try {
dest_stream.close();
} catch (IOException i) {
i.printStackTrace();
}
}
if (conn_sock != null) {
try {
conn_sock.close();
} catch (IOException i) {
i.printStackTrace();
}
}
}
}
}

java 网络编程之TCP通信和简单的文件上传功能的更多相关文章

  1. Java网络编程之TCP通信

    一.概述 Socket类是Java执行客户端TCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信.Socket类的方法会建立和销毁连接,设置各种Socket选项. Server ...

  2. java 网络编程之UDP通信和简单的群聊程序

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载.   ...

  4. Java网络编程之TCP

    Java网络编程之TCP ​ TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建 ...

  5. java网络编程之TCP通讯

    java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...

  6. nodejs 实现简单的文件上传功能

    首先需要大家看一下目录结构,然后开始一点开始我们的小demo. 文件上传总计分为三种方式: 1.通过flash,activeX等第三方插件实现文件上传功能. 2.通过html的form标签实现文件上传 ...

  7. Python 简单的文件上传功能

    简单地在程序当前目录下上传一张图片: 1.png 到程序的 yuan 文件夹下.这里使用的是固定参数 post,如果后期有需求,可以增加判断来更加完善程序. # server 端 import soc ...

  8. 4.Java网络编程之TCP/UDP

    常见传输协议: UDP , TCP UDP协议:    特点:         1.将数据及源和目的封装成数据包中,不需要建立连接         2.每个数据包的大小限制在64K内         ...

  9. java网络编程之TCP实例

    Dgram类 package Socket; import java.net.DatagramPacket; import java.net.InetAddress; public class Dgr ...

随机推荐

  1. Linux 笔记 #03# 在 Debian远程服务器上运行 Java socket程序

    我试图做什么:把我的破代码放到服务器上运行,并成功与客户端进行 socket通信. 预备环境:刚安装好 MySQL 和 JVM 的 Linux远程服务器(Debian 8)一台. 主要有如下几个步骤: ...

  2. virtio 简介

    我的微信公众号 aCloudDeveloper 专注于云计算技术,互联网技术,生活感悟,打造干货分享平台,每周至少一更,欢迎小伙伴们多多关注! 什么是 virtio virtio 是一种 I/O 半虚 ...

  3. MongoDB的安装与配置

    一.安装包安装: 1.安装 #1.安装路径为D:\MongoDB,将D:\MongoDB\bin目录加入环境变量 #2.新建目录与文件D:\MongoDB\data\dbD:\MongoDB\log\ ...

  4. Node+mongodb线上部署到阿里云

    Node+mongodb线上部署到阿里云 部署使用的主要工具是pm2+nginx,使用码云的私有仓库,自动部署到服务器,私有仓库和服务器要事先设置好免密码登录.使用DNSPOD进行域名解析.事先准备好 ...

  5. deeplearning.ai 构建机器学习项目 Week 1 机器学习策略 I 听课笔记

    这门课是讲一些分析机器学习问题的方法,如何更快速高效的优化机器学习系统,以及NG自己的工程经验和教训. 1. 正交化(Othogonalization) 设计机器学习系统时需要面对一个问题是:可以尝试 ...

  6. Gulp开发教程(翻译)

    Building With Gulp =================== 原文地址 翻译出处 原创翻译,有不当的地方欢迎指出.转载请指明出处.谢谢! 对网站资源进行优化,并使用不同浏览器测试并不是 ...

  7. UVA 11636-Hello World!(水题,猜结论)

    UVA11636-Hello World! Time limit: 1.000 seconds When you first made the computer to print the sentenc ...

  8. python笔记一(正则表达式)

    #!/usr/bin/env python # -*- coding: utf-8 -*- # 1 如果直接给出字符,则表示精确匹配 # 2 \d 表示数字, \w 表示字母或数字, . 可以匹配任意 ...

  9. iOS扩展——Objective-C开发编程规范

    最近准备开始系统学习一个完整项目的开发流程和思路,在此之前,我们需要对iOS的开发变成规范进行更系统和详尽的学习,随意对编程规范进行了整理和学习.本文内容主要转载自:Objective-C-Codin ...

  10. powerdesign