java语言网络编程之TCP通信和简单的文件上传功能实例[Java代码]
龚超 2018-07-20 来源 : 阅读 741 评论 0

摘要:本文主要向大家介绍了java语言网络编程之TCP通信和简单的文件上传功能实例,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了java语言网络编程之TCP通信和简单的文件上传功能实例,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

TCP通信需要明确的几点:

tcp通信是面向连接的,需要先启动服务端,再启动客户端。

客户端和服务端都要创建套接字对象,客户端需要指定服务端套接字(ip+port),而服务端必须指定服务端口。


Socket client_socket = new Socket("192.168.100.17",8888); //客户端套接字(Socket类的套接字为已连接套接字)

ServerSocket listen_socket = new ServerSocket(8888); //服务端套接字,此时为监听套接字(已经bind()地址和端口了)



复制代码

服务端需要使用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();

}

}


复制代码

客户端需要根据已连接套接字获取输出流,服务端需要根据套接字获取输入流。当然,既然有了已连接套接字,那么获取无论哪一端都可以获取到输入流、输出流。


OutputStream send_stream = client_socket.getOutputStream(); //客户端获取输出流

InputStream recv_stream = server_socket.getInputStream();

复制代码

服务端应主动关闭已连接套接字,至于监听套接字则在合适的地方关闭。

服务端应该循环不断地负责接收。

简单的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实现文件上传功能:

客户端除了套接字的输出流,还有读取本地文件的输入流,还有套接字的输入流来读取来自服务端的反馈信息。

服务端也同样有三流:套接字的输入、输出流,写入上传目标文件的输出流。

客户端读取本地文件的所有数据后,需要使用套接字的shutdownOutput()来通知服务端套接字的输出流已到末尾。

服务端为了能为多人提供上传功能,需要使用多线程实现并发连接。

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频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长针对企业软件开发的产品设计及开发的细节与流程设计课程内容。座右铭:大道至简!

  • 370
    文章
  • 23419
    人气
  • 87%
    受欢迎度

已有23人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
WEB前端必须会的基本知识题目
经验技巧 93% 的用户喜欢
Java语言中四种遍历List的方法总结(推荐)
经验技巧 91% 的用户喜欢
Java语言之SHA-256加密的两种实现方法详解
经验技巧 75% 的用户喜欢
java语言实现把两个有序数组合并到一个数组的实例
经验技巧 75% 的用户喜欢
通过Java语言代码来创建view的方法
经验技巧 80% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
周鸣君
周鸣君 联系TA
擅长Hadoop/Spark大数据技术
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程