java 网络编程之TCP通信和简单的文件上传功能实例
TCP通信需要明确的几点:
tcp通信是面向连接的,需要先启动服务端,再启动客户端。
客户端和服务端都要创建套接字对象,客户端需要指定服务端套接字(ip+port),而服务端必须指定服务端口。
Socketclient_socket=newSocket("192.168.100.17",8888);//客户端套接字(Socket类的套接字为已连接套接字) ServerSocketlisten_socket=newServerSocket(8888);//服务端套接字,此时为监听套接字(已经bind()地址和端口了)
服务端需要使用accept()方法将监听套接字转变为已连接套接字。这个监听套接字可以生成多个已连接套接字,这样连接后还能监听其他客户端的请求。因此,这里应该使用多线程实现并发访问。获得了已连接套接字,就可以获取很多客户端的信息,例如客户端的ip地址,发送请求的端口等。
Socketserver_scoket=socket.accept(); Socketserver_scoket2=socket.accept(); Socketserver_scoket3=socket.accept();
服务端要实现并发连接,大致使用如下代码:其中ThreadTask是线程任务对象。
publicstaticvoidmain(String[]args)throwsIOException{ ServerSocketlisten_sock=newServerSocket(8888);//监听套接字只需创建一个,因此在任务之外 while(true){//每建立一个连接,就开启一个线程 Socketconn_sock=listen_sock.accept();//没有新连接进来时,main主线程阻塞在此 newThread(newThreadTask(conn_sock)).start(); } }
客户端需要根据已连接套接字获取输出流,服务端需要根据套接字获取输入流。当然,既然有了已连接套接字,那么获取无论哪一端都可以获取到输入流、输出流。
OutputStreamsend_stream=client_socket.getOutputStream();//客户端获取输出流 InputStreamrecv_stream=server_socket.getInputStream();
服务端应主动关闭已连接套接字,至于监听套接字则在合适的地方关闭。
服务端应该循环不断地负责接收。
简单的Client端:
importjava.io.IOException; importjava.io.OutputStream; importjava.net.Socket; publicclassTCPClient{ publicstaticvoidmain(String[]args){ //1.创建客户端套接字 Socketc_sock=null; OutputStreamclient_outstream=null; try{ c_sock=newSocket("192.168.0.124",8888); //2.获取输出流 client_outstream=c_sock.getOutputStream(); //3.输出数据 client_outstream.write("Hello,i'mcoming".getBytes()); }catch(IOExceptione){ e.printStackTrace(); }finally{ if(c_sock!=null){ try{ c_sock.close(); }catch(IOExceptione){ e.printStackTrace(); } } } } }
简单的Server端:
importjava.io.BufferedReader; importjava.io.IOException; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.net.ServerSocket; importjava.net.Socket; publicclassTCPServer{ publicstaticvoidmain(String[]args){ //1.创建监听套接字 ServerSocketlisten_sock=null; try{ listen_sock=newServerSocket(8888); }catch(IOExceptioni){ i.printStackTrace(); } Socketserver_sock=null; InputStreamin_sock=null; while(true){ try{ //2.和客户端建立连接,生成已连接套接字,并获取客户端ip地址 server_sock=listen_sock.accept(); Stringclient_ip=server_sock.getInetAddress().getHostAddress(); System.out.println("Client:"+client_ip+"connected"); //3.根据已连接套接字,获取输入流,读取客户端发送的数据 in_sock=server_sock.getInputStream(); BufferedReaderbufr=newBufferedReader(newInputStreamReader(in_sock)); Stringline=null; while((line=bufr.readLine())!=null){ System.out.println(line); } //4.关闭已连接套接字 server_sock.close(); }catch(IOExceptione){ e.printStackTrace(); } } } }
以下是tcp实现文件上传功能:
客户端除了套接字的输出流,还有读取本地文件的输入流,还有套接字的输入流来读取来自服务端的反馈信息。
服务端也同样有三流:套接字的输入、输出流,写入上传目标文件的输出流。
客户端读取本地文件的所有数据后,需要使用套接字的shutdownOutput()来通知服务端套接字的输出流已到末尾。
服务端为了能为多人提供上传功能,需要使用多线程实现并发连接。
Client端:
importjava.io.BufferedReader; importjava.io.FileInputStream; importjava.io.IOException; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.io.OutputStream; importjava.net.Socket; publicclassUploadClient{ publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub Stringserver_addr="192.168.0.124"; intserver_port=8888; Socketsend_sock=null; FileInputStreamlocal_read=null; try{ //1.客户端套接字 send_sock=newSocket(server_addr,server_port); //2.获取连接管道的输出流 OutputStreamsend_stream=send_sock.getOutputStream(); //3.字节输入流读取本地文件数据,并使用套接字的输出流发送出去 local_read=newFileInputStream("d:/myjava/net/SQL.docx"); byte[]buf=newbyte[1024]; intlen=0; while((len=local_read.read(buf))!=-1){ send_stream.write(buf,0,len); } //4.标记输出流到结尾 send_sock.shutdownOutput(); //5.接收服务端的反馈数据,如上传成功,上传失败等 InputStreamrecv_stream=send_sock.getInputStream(); BufferedReaderack_recv=newBufferedReader(newInputStreamReader(recv_stream)); Stringline=null; while((line=ack_recv.readLine())!=null){ System.out.println(line); } }catch(IOExceptioni){ i.printStackTrace(); }finally{ if(send_sock!=null){ try{ send_sock.close(); local_read.close(); }catch(IOExceptioni1){ i1.printStackTrace(); } } if(local_read!=null){ try{ local_read.close(); }catch(IOExceptioni2){ i2.printStackTrace(); } } } } }
Server端:
importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.InputStream; importjava.io.OutputStream; importjava.net.ServerSocket; importjava.net.Socket; publicclassUploadServer{ publicstaticvoidmain(String[]args)throwsIOException{ ServerSocketlisten_sock=newServerSocket(8888);//监听套接字只需创建一个,因此在任务之外 while(true){//每建立一个连接,就开启一个线程 Socketconn_sock=listen_sock.accept();//没有新连接进来时,main主线程阻塞在此 newThread(newUploader(conn_sock)).start(); } } } classUploaderimplementsRunnable{ privateFiledest_dir=newFile("d:/temp");//上传目录 privateSocketconn_sock=null;//连接套接字 InputStreamrecv_stream=null; FileOutputStreamdest_stream=null; Uploader(Socketconn_sock)throwsIOException{ this.conn_sock=conn_sock; } publicvoidrun(){ try{ if(!dest_dir.exists()){ dest_dir.mkdirs(); } //1.获取连接管道的输入流 recv_stream=conn_sock.getInputStream(); //客户端ip Stringclient_ip=conn_sock.getInetAddress().getHostAddress(); System.out.println(client_ip+".....connected"); //2.文件的上传位置,即输出目标,以ip命名。如果文件已存在,则使用括号加数字新建文件,如"192.168.100.23(1).txt" Filedest_file=newFile(dest_dir,client_ip+".docx"); intcount=1; while(dest_file.exists()){ dest_file=newFile(dest_dir,client_ip+"("+count+")"+".docx"); count++; } //3.读取数据并写入目标文件 dest_stream=newFileOutputStream(dest_file); byte[]buf=newbyte[1024]; intlen=0; while((len=recv_stream.read(buf))!=-1){ dest_stream.write(buf,0,len); } //4.向客户端反馈信息 OutputStreamack_send=conn_sock.getOutputStream(); byte[]text="uploadsuccessful!".getBytes(); ack_send.write(text); }catch(IOExceptione1){ e1.printStackTrace(); }finally{ if(dest_stream!=null){ try{ dest_stream.close(); }catch(IOExceptioni){ i.printStackTrace(); } } if(conn_sock!=null){ try{ conn_sock.close(); }catch(IOExceptioni){ i.printStackTrace(); } } } } }
以上这篇java网络编程之TCP通信和简单的文件上传功能实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。