黑马程序员——网络编程(二)------UDP、TCP和多线程

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

                               java网络编程

1、基于UDP协议的网络编程
    UDP协议是一种不可靠的网络协议,它在通讯实例的两端个建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送和接受数据报的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送和接收的数报。DatagramSocket本身并不负责维护状态和产生IO流。它仅仅负责接收和发送数据报。使用receive(DatagramPacket p)方法接收,使用send(DatagramPacket p)方法发送。

服务器端示例代码:

import java.net.*;
import java.io.*;
class UdpRece 
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds = new DatagramSocket(10000);
		while (true)
		{
			byte[] buf = new byte[1024];
			DatagramPacket dp = new DatagramPacket(buf,buf.length);
			ds.receive(dp);
			String ip = dp.getAddress().getHostAddress();
			String data = new String(dp.getData(),0,dp.getLength());
			System.out.println(ip+"::"+data);
		}
	}
}

客户端示例代码:

import java.net.*;
import java.io.*;
class  UdpSend
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds=new DatagramSocket(8888);

			BufferedReader bufr=
				new BufferedReader(new InputStreamReader(System.in));
			String line=null;
			while ((line=bufr.readLine())!=null)
			{
				if ("over".equals(line))
				break;
				byte[] buf = line.getBytes();
				DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("219.228.251.57"),10000);
				ds.send(dp);
			}
		ds.close();
	}
}

2、基于TCP协议的网络编程

    TCP协议是一种可靠的通络协议,通信两端的Socket使得它们之间形成网络虚拟链路,两端的程序可以通过虚拟链路进行通讯。Java使用socket对象代表两端的通信端口,并通过socket产生的IO流来进行网络通信。

2.1 ServerSocket
    在两个通信端没有建立虚拟链路之前,必须有一个通信实体首先主动监听来自另一端的请求。ServerSocket对象使用accept()方法用于监听来自客户端的Socket连接,如果收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket对象。如果没有连接,它将一直处于等待状态。通常情况下,服务器不应只接受一个客户端请求,而应该通过循环调用accept()不断接受来自客户端的所有请求。
    这里需要注意的是,对于多次接收客户端数据的情况来说,一方面可以每次都在客户端建立一个新的Socket对象然后通过输入输出通讯,这样对于服务器端来说,每次循环所接收的内容也不一样,被认为是不同的客户端。另外,也可以只建立一次,然后在这个虚拟链路上通信,这样在服务器端一次循环的内容就是通信的全过程。

服务器端示例代码:
import java.net.*;
import java.io.*;
class  TextServer
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss=new ServerSocket(9999);
		Socket s= ss.accept();
		BufferedReader bufIn = 
			new BufferedReader(new InputStreamReader(s.getInputStream()));
		PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true);
		String line=null;
		while ((line=bufIn.readLine())!=null)
		{
			out.println(line);
		}
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		pw.println("上传成功!");
		out.close();
		s.close();
		ss.close();
	}
}

2.2 Socket
     使用Socket可以主动连接到服务器端,使用服务器的IP地址和端口号初始化之后,服务器端的accept便可以解除阻塞继续向下执行,这样就建立了一对互相连接的Socket。
客户端示例代码:
import java.net.*;
import java.io.*;
class  TextClient
{
	public static void main(String[] args) throws Exception
	{
		Socket s=new Socket("219.228.251.57",9999);
		BufferedReader bufr = 
			new BufferedReader(new FileReader("UdpSend.java"));
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		String line=null;
		while ((line=bufr.readLine())!=null)
		{
			out.println(line);
		}
		s.shutdownOutput();
		BufferedReader bufIn =
			new BufferedReader(new InputStreamReader(s.getInputStream()));
		String str = bufIn.readLine();
		System.out.println(str);
		bufr.close();
		s.close();

	}
}

3、网络编程中的多线程
   在复杂的通讯中,使用多线程非常必要。对于服务器来说,它需要接收来自多个客户端的连接请求,处理多个客户端通讯需要并发执行,那么就需要对每一个传过来的Socket在不同的线程中进行处理,每条线程需要负责与一个客户端进行通信。以防止其中一个客户端的处理阻塞会影响到其他的线程。对于客户端来说,一方面要读取来自服务器端的数据,另一方面又要向服务器端输出数据,它们同样也需要在不同的线程中分别处理。下面一个登录小例子:
服务器端:
import java.util.*;
import java.io.*;
import java.net.*;
class UserThread implements Runnable
{
	private Socket s;
	UserThread(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+".........connected");
		try
		{
			for (int i=0;i<3 ;i++ )
			{
			
			BufferedReader bufIn = 
				new BufferedReader(new InputStreamReader(s.getInputStream()));
			String name = bufIn.readLine();
			BufferedReader bufr = new BufferedReader(new FileReader("user.txt"));
			PrintWriter out = new PrintWriter(s.getOutputStream());
			String line = null;
			boolean flag=false;
			while ((line=bufr.readLine())!=null)
			{
				if (line.equals(name))
				{
					flag=true;
					break;
				}
			}
			if (flag)
			{
				System.out.println(name+",已登录");
				out.println(name+",欢迎光临");
				break;
			}
			else 
			{
				System.out.println(name+",尝试登录");
				out.println(name+",用户名不存在");
			}
		}
		s.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException(ip+"校验失败");
		}
	}
}
class LoginServer 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss= new ServerSocket(10000);
		while (true)
		{
			Socket s = ss.accept();
			new Thread(new UserThread(s)).start();
		}
		
	}
}
客户端:
import java.util.*;
import java.io.*;
import java.net.*;
class  LoginClient
{
	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("219.228.251.23",10000);
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		BufferedReader bufIn =
			new BufferedReader(new InputStreamReader(s.getInputStream()));
		for (int i=0;i<3 ; i++)
		{
			String line = bufr.readLine();
			if (line==null)
				break;
			out.println(line);
			String info = bufIn.readLine();
			System.out.println("info"+info);
			if (info.contains("欢迎"))
			break;e
		}
		bufr.close();
		s.close();
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值