首页 > 编程 > Java > 正文

java 网络编程之TCP通信和简单的文件上传功能实例

2019-11-26 10:25:34
字体:
来源:转载
供稿:网友

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 网络编程之TCP通信和简单的文件上传功能实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表