您的位置:首页 > 理论基础 > 计算机网络

java实现的基于TCP网络编程步骤

2014-03-30 23:29 741 查看
参考 java 程序设计教程(第二版)雍俊海老师编著的书12章

服务器端程序设计模型的建立通常由如下五个步骤组成:

(1)在服务器端,首先要创建ServerSocket的实例对象,注册在服务器端进行连接的端口号以及允许连接的最大客户数目。

(2)调用ServerSocket的成员方法accept来等待并监听来自客户端的连接。当有客户端与改服务器端建立连接时,类ServerSocket的成员方法accept将返回连接通道在服务器端的Socket。套接字的类型是Socket,通过该套接字可以与客户端进行数据通信。

(3)调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)。当使用套接字网络上传送对象时候,需要进行序列化。

(4)通过获得的输入流和输出流与客户端进行数据通信,并处理从客户端获得的数据以及需要向客户端发送的数据。

(5)在数据通信完毕之后,关闭输入流、输出流和套接字(Socket)。

在服务器端创建类ServerSocket的实例对象,并且调用类Serversocket的成员方法accept之后,服务器端开始一直等待客户端与其连接。

客户端程序设计模型的建立通常由如下四个步骤组成:

(1)在客户端,创建Socket的实例对象,与服务器端建立连接。在创建Socket的实例对象时需要制定服务器端的主机名以及进行连接的端口号,即在服务器端构造类Serversocket实例对象时所注册的端口号。主机名与端口号完全匹配才能建立起连接,并构造出类Socket的实例对象。在构造出类Socket的实例对象之后的步骤与服务器端的相应步骤基本一致。

(2)调用类Socket的成员方法getInputStream和getOutputStream获得该套接字所对应的输入流(InputStream)和输出流(OutputStream)。当使用套接字网络上传送对象时候,需要进行序列化。

(3)通过获得的输入流和输出流与客户端进行数据通信,并处理从服务器端获得的数据以及需要向服务器端发送的数据。

(4)在数据通信完毕之后,关闭输入流、输出流和套接字(Socket)。

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。 

客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

C/S模式套接字的连接示意图:



例子

(1)服务器端单一向客户端发消息,客户端收到消息,一次通信结束,客户端程序结束,而服务器端继续等待下一个客户端的连接。终止程序,要在控制台同时按ctrl +c.

结果如下图:



代码如下

服务器端:

package wjl;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class J_Server
{
	public static void main(String[] args)
	{
		int port = 8083;
		try{
		ServerSocket server = new ServerSocket(port);
		while(true)
		{
		Socket client = server.accept();
		System.out.println("服务器端接收到来自客户端的连接");
		
		OutputStream o = client.getOutputStream();
		DataOutputStream d = new DataOutputStream(o);
		d.writeUTF("服务器端向客户端问好");//writeUTF()将两个字节长度信息写入输出流,紧随其后的是修改后的字符串中的每个字符的utf - 8表示。
		d.close();
		o.close();		
		}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
	}

}


客户端

package wjl;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.Socket;

public class J_Client
{
	public static void main(String[] args)
	{
		int port = 8083;
		try
		{
			Socket client = new Socket("localhost",port);
			InputStream o = client.getInputStream();
			DataInputStream d = new DataInputStream(o); 
			System.out.println("客户端收到:" + d.readUTF());//readUTF()读到的是以UTF格式编码的输入流中的字符,返回字符串。
			d.close();
			o.close();
		}
		catch (Exception e)
		{
			// TODO: handle exception
			e.printStackTrace();
		}
	}

}


(2)服务器端和客户端都可以收发消息,不过一次通信后,服务器端和客户端都运行结束了。

结果如下图:



服务器端

package wjl;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class  WebServer
{
	public static void main(String[] args) 
	{ 
		int port = 9999;/*开辟一个端口就是开启一个服务了---端口的分配必须是唯一的,因为端口是为了唯一标识每台计算机唯一服务的 
         * 端口号是从0~65535之间的,前1024个端口已被Tcp/Ip作为保留端口,因此自己分配的端口只能是1024以后的*/  
		try
		{
		ServerSocket server = new ServerSocket(port);//创建服务器端套接字
		Socket client = server.accept();//监听器。服务器端建立自己的套接字

		OutputStream o = client.getOutputStream();//服务器端打开自己的输出流
		BufferedOutputStream b = new BufferedOutputStream(o);//使用带缓存的输出流
        InputStream i = client.getInputStream();//服务器端打开自己输入流

		o.write("hello,I am server".getBytes());//服务器hello,I am server写入输出流--》客户端
		b.write("hello,I am server".getBytes());
		b.flush();

		byte[] buf = new byte[100];//存储套接字通道中读到的服务器端输出流的字符流
		int len = i.read(buf);//read(byte[] b)从当前服务器端的输入流中(即客户端的输出流)读取出来存储到字符数组buf中,该方法返回的是读出的字符数组长度。
		System.out.println(new String(buf,0,len));//客户端--》服务器 。new String(buf,0,len)是将字符数组buf从下标零到len的每个字符构成一个字符串
		//System.out是java.io.OutputStream类型的变量
		

		o.close();//服务器端关闭输出流
		b.close();
		i.close();//客户端关闭输入流
		client.close();//客户端关闭套接字
		server.close();//服务端关闭套接字
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}


客户端

package wjl;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class WebClient 
{
	public static void main(String[] args) 
	{
		int port=9999;
		try{
		Socket client = new Socket(InetAddress.getByName("localhost"),port);//创建客户器端套接字
		//InetAddress---表示互联网协议(IP)地址  ---InetAddress.getByName("www.163.com")--在给定主机名的情况下确定主机的IP地址--如果参数为null,获得的是本机的IP地址
		OutputStream o = client.getOutputStream();//打开客户端的输出流
		InputStream i = client.getInputStream();//打开客户端的输入流
		byte[] buf = new byte[100];
		int len = i.read(buf);
		System.out.println(new String(buf,0,len));//服务器--》客户端
		
		o.write("hello,I am client".getBytes());//客户端hello,I am client写到输出流--》服务器.write(byte[] b)将字节数组b的各个字节写入当前文件中。
		o.close();//关闭客户端的输出流
		i.close();//关闭客户端的输入流
		client.close();//关闭套接字
		}
		catch(Exception e)
		{
			e.printStackTrace();
			
		}

	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: