java 网络编程之TCP通信和简单的文件上传功能实例
程序员文章站
2023-12-09 14:38:33
tcp通信需要明确的几点:
tcp通信是面向连接的,需要先启动服务端,再启动客户端。
客户端和服务端都要创建套接字对象,客户端需要指定服务端套接字(ip+port),而...
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通信和简单的文件上传功能实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。