基于Tcp协议的网络编程



<pre name="code" class="java">public class Client {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws UnknownHostException, IOException {
		// TODO Auto-generated method stub
		Socket s=new Socket("127.0.0.1",3000);
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line=br.readLine();
		System.out.println(line);;
		br.close();
		s.close();

	}

}

public class Server {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		ServerSocket server=new ServerSocket(3000);
		while(true)
		{
			//获取连接的客户端
			Socket s=server.accept();
			PrintStream ps=new PrintStream(s.getOutputStream());//向Socket输入数据
			ps.println("您好,收到服务器发出的新年祝福");
			ps.close();
			s.close();
		}

	}

}

加入多线程

前面的代码只是实现了两个实体的简单通信,实际中的客户端可能需要和服务器端保持较长时间的通信,即服务器端需要不断的读取客户端数据,并向客户端写入数据,客户端也需要不断的读取服务器端的数据,并向服务器端写入数据。

一个命令行界面的C/S聊天室应用,服务器端应该包含多个线程,每个Socket对应一个线程,该线程负责读取Socket对应输入流的数据(从客户端发送过来的数据),并将输入的数据向每个Socket输出流发送一个,因此需要在服务器端使用List来保存所有的Socket

public class MyServer {
	//用来保存所有的Socket对象
	public static ArrayList<Socket>  list= new ArrayList<Socket>();
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		ServerSocket server = new ServerSocket(3000);
		while(true)
		{
			Socket socket = server.accept();
			list.add(socket);
			//为每一个Socket启动线程
			new Thread(new ServerThread(socket)).run();
		}
	}
}

public class ServerThread implements Runnable {
	Socket s=null;
	BufferedReader br=null;
	public ServerThread(Socket socket) throws IOException
	{
		this. s = socket;
		//初始化Socket对应的输入流
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try
		{
			String content = null;
			while((content = readFromClient())!=null)
			{
				for(Socket s:MyServer.list)
				{
					PrintStream ps = new PrintStream(s.getOutputStream());
					ps.println(content);
				}
			}
		}catch(IOException e)
		{
			e.printStackTrace();
		}

	}
	//定义读取客户端数据的方法
	private String readFromClient() {
		// TODO Auto-generated method stub
		try
		{
			return br.readLine();
		}catch(IOException e)
		{
			MyServer.list.remove(s);
		}
		return null;
	}
}

上面的服务器端线程类不断的读取客户端数据,程序使用readFromClient()方法来读取客户端数据,如果读取数据过程中捕获到异常,则表明该Socket对应的客户端Socket出现了问题,将从list集合中删除。

每个客户端包含两个线程,一个负责读取用户的键盘输入,并将用户输入的数据写入Socket对应的输出流中,一个负责读取Socket对应输入流中的数据(从服务器端发送过来的数据),并将这些数据打印输出。

public class MyClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		// TODO Auto-generated method stub
		Socket s = new Socket("127.0.0.1",3000);
		new Thread(new ClientThread(s)).start();
		PrintStream ps = new PrintStream(s.getOutputStream());
		String line = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while((line=br.readLine()) != null)
		{
			ps.println(line);
		}
	}
}
public class ClientThread implements Runnable {
	private Socket s=null;
	BufferedReader br=null;
	public ClientThread(Socket socket) throws IOException
	{
		this.s=socket;
		br=new BufferedReader(new InputStreamReader(s.getInputStream()));
	}

	public void run() {
		// TODO Auto-generated method stub
		try
		{
			String content =null;
			while((content =br.readLine())!=null)
			{
				System.out.println(content);
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}








里面包含聊天室的客户端和服务器端的源文件和一份完整的设计报告。 一、 系统概要 本系统能实现基于VC++的网络聊天室系统。有单独的客户端、服务器端。 服务器应用程序能够接受来自客户端的广播,然后向客户端发送本机的IP与服务端口,让客户端接入到服务器进行聊天,检测用户名是否合法(重复),服务器责接收来自客户端的聊天信息,并根据用户的需求发送给指定的人或所有人,能够给出上线下线提示。客户端能够发出连接请求,能编辑发送信息,可以指定发给单人或所有人,能显示聊天人数,上线下线用户等。 二、 通信规范的制定 服务请求规范: 服务器端: (1) 创建一个UDP的套接字,接受来自客户端的广播请求,当请求报文内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”时,接受请求,给客户端发送本服务器TCP聊天室的端口号。 (2) 创建一个主要的TCP协议的套接字负责客户端TCP连接 ,处理它的连接请求事件。 (3)在主要的TCP连接协议的套接字里面再创建TCP套接字保存到动态数组里,在主要的套接字接受请求后 ,就用这些套接字和客户端发送和接受数据。 客户端: (1) 当用户按“连接”按钮时,创建UDP协议套接字,给本地计算机发广播,广播内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”。 (2)当收到服务器端的回应,收到服务器发来的端口号后,关闭UDP连接。根据服务器的IP地址和端口号重新创建TCP连接。 故我思考:客户端一定要知道服务器的一个端口,我假设它知道服务器UDP服务的端口,通过发广播给服务器的UDP服务套接字,然后等待该套接字发回服务器TCP聊天室服务的端口号,IP地址用ReceiveForom也苛刻得到。 通信规范 通信规范的制定主要跟老师给出的差不多,并做了一小点增加: (增加验证用户名是否与聊天室已有用户重复,在服务器给客户端的消息中,增加标志0) ① TCP/IP数据通信 --- “聊天”消息传输格式 客户机 - 服务器 (1)传输“用户名” STX+1+用户名+ETX (2) 悄悄话 STX+2+用户名+”,”+内容+ETX (3) 对所有人说 STX+3+内容+ETX 服务器- 客户机 (0)请求用户名与在线用户名重复 //改进 STX+0+用户名+EXT (1)首次传输在线用户名 STX+1+用户名+ETX (2)传输新到用户名 STX+2+用户名+ETX (3)传输离线用户名 STX+3+用户名+ETX (4)传输聊天数据 STX+4+内容+ETX (注:STX为CHR(2),ETX 为CHR(3)) 三、 主要模块的设计分析 四、 系统运行效果 (要求有屏幕截图) 五、 心得与体会
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值