java网络编程

UDP:

a)        将数据及源和目的封装成数据包中,不需要建立连接

b)        每个数据报的大小限制在64K内

c)        因无连接,是不可靠协议

d)        不需要建立连接,速度快

TCP:

a)        建立连接,形成传输数据的通道

b)        在连接中进行大数据传输

c)        通过三次握手完成连接,是可靠协议


应用:

1,TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP

2,UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

基于Socket的java网络编程

a)        就是为网络服务提供的一种机制

b)        通信的两端都有Socket

c)        网络通信其实就是socket间的通信

d)        数据在2个Socket间通过IO传输

 

1,什么是Socket

网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。

2,Socket通讯的过程

Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。

对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:

  (1) 创建Socket;

  (2) 打开连接到Socket的输入/出流;

  (3) 按照一定的协议对Socket进行读/写操作;

  (4) 关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)

3,创建Socket

创建Socket

java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便。其构造方法如下:

  Socket(InetAddress address, int port);

  Socket(InetAddress address, int port, boolean stream);

  Socket(String host, int prot);

  Socket(String host, int prot, boolean stream);

  Socket(SocketImpl impl)

  Socket(String host, int port, InetAddress localAddr,int localPort)

  Socket(InetAddress address, int port, InetAddresslocalAddr, int localPort)

  ServerSocket(int port);

  ServerSocket(int port, int backlog);

  ServerSocket(int port, int backlog, InetAddressbindAddr)

  其中address、host和port分别是双向连接中另一方的IP地址、主机名和端口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。

  Socket client = new Socket("127.0.01.", 80);

  ServerSocket server = new ServerSocket(80);

  注意,在选择端口时,必须小心。每一个端口提供一种特定的服务,只有给出正确的端口,才 能获得相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23, 所以我们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。端口范围:0-65535,其中0~1024系统使用或保留端口

  在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。

4,支持多客户的client/server程序

前面的Client/Server程序只能实现Server和一个客户的对话。在实际应用 中,往往是在服务器上运行一个永久的程序,它可以接收来自其他多个客户端的请求,提供相应的服务。为了实现在服务器方给多个客户提供服务的功能,需要对上 面的程序进行改造,利用多线程实现多客户机制。服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响 应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。

5,简单的Client/Server程序

获得指定url的ip地址及名字

package com.wj.ip;

 

import java.net.InetAddress;

import java.net.UnknownHostException;

/**

 * 得到ip地址

 * @author wJing

 * time:2014/2/9

 */

public class IPDemo1 {

   /**

    *

    * @param args

    * @throws Exception

    */

   public staticvoid main(String[] args) throws Exception {

       InetAddress i= InetAddress.getLocalHost();

       System.out.println(i.toString());

       System.out.println(i.getHostName());

       System.out.println(i.getHostAddress());

      

       InetAddressia = InetAddress.getByName("127.0.0.1");

       System.out.println("address:"+ia.getHostAddress());

       System.out.println("ip:"+ ia.getHostName());

   }

}

简单的Client(发送文本):

package com.wj.client;

 

import java.io.BufferedReader;

import java.io.DataOutputStream;

import java.io.FileReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

 

/**

 *

 * @author wJing

 * time:2014-2-915:09:54

 * 把客户端的一个文件传递到服务端,模拟

 */

public class TextClient {

 

   public staticvoid main(String[] args) throws Exception, IOException {

       Socket s =new Socket("localhost", 9999);

      

       BufferedReaderbuf = new BufferedReader(new FileReader("d:\\abcde.txt"));

      

       PrintWriterwriter = new PrintWriter(s.getOutputStream(),true);

      

       /*

       /

       //时间戳,确定文件的结束标记

       DataOutputStreamdos = new DataOutputStream(s.getOutputStream());

       long time =System.currentTimeMillis();

       dos.writeLong(time);

      

      

      

       */

      

      

       String line =null;

      

       while((line =buf.readLine()) != null) {

          writer.println(line);

       }

       //关闭客户端输出流

      

       s.shutdownOutput();

      

      

      

//     writer.println(time);//文件读完以后再发一次时间戳

       ///

       BufferedReaderin = new BufferedReader(new InputStreamReader(s.getInputStream()));

       String str =in.readLine();

       System.out.println(str);

      

       buf.close();

       s.close();

   }

 

}

简单的Server(接收文本):

package com.wj.server;

 

import java.io.BufferedReader;

import java.io.DataInputStream;

import java.io.FileWriter;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

 

public class TextServer {

 

   public staticvoid main(String[] args) throws Exception {

       ServerSocketss = new ServerSocket(9999);

       Socket s =ss.accept();

      

       BufferedReaderbufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

      

       PrintWriterin = new PrintWriter(new FileWriter("e://copy.txt"),true);

      

       /**

        *

       ///

       DataInputStreamdis = new DataInputStream(s.getInputStream());

       long time =dis.readLong();

       ///

      

       /**

        * 方式1:发送一个标记给服务器

        * 方式2:使用时间戳当作一个标记

        * 方式3:使用socket的shutdowninput、shutdownoutput

        */

      

      

       String line =null;

       while((line =bufIn.readLine()) != null) {

//        if(line.equals(time)){

//            break;

//        }

          in.println(line);

       }

      

       PrintWriterout = new PrintWriter(s.getOutputStream(), true);

       out.println("上传成功");

      

       in.close();

       s.close();

       ss.close();

   }

 

}

简单的Client(发送图片):

package com.wj.client;

 

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.net.UnknownHostException;

 

/**

 *

 * @author wJing

 * time:2014-2-916:38:57

 * 上次图片

 */

public class ImageClient {

 

   public staticvoid main(String[] args) throws Exception, IOException {

       Socket s =new Socket("localhost", 1520);

       FileInputStreamfis = new FileInputStream("d:\\1.jpg");

      

       OutputStreamout = s.getOutputStream();

      

       byte[] buf =new byte[1024];

      

       int len = 0;

      

       while((len =fis.read(buf)) != -1) {

          out.write(buf,0, len);

       }

      

       //告诉服务器数据已写完

       s.shutdownOutput();

      

       InputStreamin = s.getInputStream();

       byte[] bufIn= new byte[1024];

       int num =in.read(bufIn);

      

       System.out.println(newString(bufIn, 0, num));

      

       fis.close();

       s.close();

   }

 

}

简单的Server(接收图片)

package com.wj.server;

 

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

 

class picThread implements Runnable {

   private Socket s;

   publicpicThread(Socket s) {

       this.s = s;

   }

   @Override

   public void run(){

       int count =1;

       String ip =s.getInetAddress().getAddress().toString();

       System.out.println(ip+ ".....connected");

       try {

       InputStreamin = s.getInputStream();

      

       File file =new File(ip+count + ".jpg");

       while(file.exists()){

          file = newFile(ip + "(" + count++ + ").jpg");

       }

 

       FileOutputStreamfos = new FileOutputStream(file);

 

       byte[] buf =new byte[1024];

       int len = 0;

       while((len =in.read(buf)) != -1) {

          fos.write(buf,0, len);

       }

 

       OutputStreamout = s.getOutputStream();

       out.write("上次成功".getBytes());

 

       fos.close();

       s.close();

       }catch(Exception e) {

          throw newRuntimeException(ip + "上传失败");

       }

   }

 

}

 

public class ImageServer {

   public staticvoid main(String[] args) throws Exception {

       //  UploadPic();

 

 

       //使用多线程处理多个客户端的访问

       ServerSocketss = new ServerSocket(1520);

       while(true) {

          Socket s =ss.accept();

          newThread(new picThread(s)).start();

       }

   }

 

 

   //先线程的图片上传,一个客户端连上以后只有等为他服务完成以后才能为下一个人服务

   private staticvoid UploadPic() throws IOException, FileNotFoundException {

       ServerSocketss = new ServerSocket(1520);

       //     while(true) {

       Socket s =ss.accept();

 

       InputStreamin = s.getInputStream();

 

       FileOutputStreamfos = new FileOutputStream("e:\\server.jpg");

 

       byte[] buf =new byte[1024];

       int len = 0;

       while((len =in.read(buf)) != -1) {

          fos.write(buf,0, len);

       }

 

       OutputStreamout = s.getOutputStream();

       out.write("上次成功".getBytes());

 

       fos.close();

       s.close();

       //     }

       ss.close();

   }

}

 

 

 

 

 

一个基于UDP的简单聊天程序:

package com.wj.udp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.SocketException;

 

/**

 *

 * @author wJing

 *编写一个聊天程序

 *time:2014-2-9 11:33:20

 */

 

class Send implements Runnable {

   privateDatagramSocket ds;

  

   publicSend(DatagramSocket ds) {

       this.ds = ds;

   }

  

   @Override

   public void run(){

      

       try {

          BufferedReaderin = new BufferedReader(new InputStreamReader(System.in));

          Stringline = null;

          while((line= in.readLine()) != null) {

              if("886".equals(line)){

                 break;

              }

              byte[] buf = line.getBytes();

              DatagramPacketdp = new DatagramPacket(buf, buf.length,InetAddress.getByName("localhost"), 10002);

              ds.send(dp);

          }

       } catch(Exception e) {

          throw newRuntimeException("发送端失败");

       }

   }

  

}

 

class Receive implements Runnable {

   private DatagramSocketds;

  

   publicReceive(DatagramSocket ds) {

       this.ds = ds;

   }

   @Override

   public void run(){

       try {

          while(true){

              byte[]buf = new byte[1024 * 64];

              DatagramPacketdp = new DatagramPacket(buf, buf.length);

              ds.receive(dp);

             

              Stringip = dp.getAddress().getHostAddress();

              Stringdata = new String(dp.getData(), 0, dp.getLength());

              System.out.println("ip->"+ ip + ":" + data);

          }

       } catch(Exception e) {

          throw newRuntimeException("接收失败");

       }

   }

  

}

 

public class ChatDemo {

 

   public staticvoid main(String[] args) throws Exception {

       DatagramSocketsendSocket = new DatagramSocket();

       DatagramSocketreceiveSocket = new DatagramSocket(10002);

      

       newThread(new Send(sendSocket)).run();

       newThread(new Receive(receiveSocket)).run();

   }

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值