使用socket进行信息的传递

1 篇文章 0 订阅

这是一种见得模拟qq的即时传讯程序。

一、建立服务端

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

/**
 *  建立服务端
 * @author 
 *
 */
public class TestServerSocket {
	
	public static void main(String[] args) {
		//设置为null是因为用完要在finally里面close();
		ServerSocket ss =null; 
		Socket s1= null;
		DataOutputStream dos =null;
		try {
			//设置服务的端口名为9999,一般设置四位数,1024以下的基本上被电脑所占用所以最好写大一点
			ss =new ServerSocket(9999);
			System.out.println("服务端开始运行了");
			s1 = ss.accept();//侦听开始,返回的是Socket类型
			//DateOutputStream里的参数是OutputStream,我们通过Socket里的getOutputStream获得
			dos = new DataOutputStream(s1.getOutputStream());
			//调用write方法写东西传过去。
			dos.writeUTF("aa");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//释放资源
			try {
				if(ss!=null)
				ss.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				if(s1!=null)
				s1.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				if(dos!=null)
				dos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
}

建立客户端

package com.lqx.testsocket;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * 客户端
 * @author 
 *
 */
public class TestCoilen {
	public static void main(String[] args) {
		Socket cs =null;
		DataInputStream dis = null;
		try {
			//Socket的构造方法里一个参数是地址,一个是端口。这里的127.0.0.1是本地的意思。如果要连接其他的服务端需要输入对应的IP地址和端口号
			cs =new Socket("127.0.0.1", 9999);
			dis = new DataInputStream(cs.getInputStream());
			//使用read方法可以读出来。
			System.out.println(dis.readUTF());
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(cs!=null)
				cs.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				if(dis!=null)
				dis.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
}

输出

在这里插入图片描述

服务端要先运行

然后在运行客户端

在这里插入图片描述

– 可以看出在客服端接收并输出了aa。

改进

这里只进行了一次的传输,如果想要多次传输,只需在read和write方法外加一个while方法即可

while(true) {
			dos.writeUTF("aa");}
while(true) {
			System.out.println(dis.readUTF());
			}

虽然进行了多次的传输,但是我相信大家也发现了,他是单向的传输,如果想要双向,其实很简单,只需要在服务端和客户端各自加上想要的write和read方法即可,如下

DataOutputStream dos = new DataOutputStream(cs.getOutputStream());
			
			while(true) {
			System.out.println(dis.readUTF());
			dos.writeUTF("bbb");
			}
dos = new DataOutputStream(s1.getOutputStream());
			//调用write方法写东西传过去。
			while(true) {
			dos.writeUTF("aa");
			System.out.println(dis.readUTF());
			
			}

我这样子两个控制台会分别收到aa和bbb。如果我把里面的字符串aa和bbb替换成Scanner的输入即可完成信息的传递,不过,这个方法是阻塞的所以只能一次一次的接收和发送。

上面的只能单对单的进行数据的传递,如果想要实现,对n的信息传递。类似于群聊。就需要使用到多线程。

也就是说在服务器里开启多个线程,当外部客户端需要访问时就创造一个线程对话,但是这方法也是阻塞的。也就是说一次只能传递一个消息

public static void main(String[] args) {
		ServerSocket ss;
		try {
			ss = new ServerSocket(9999);
			System.out.println("服务器开始运行");
			while (true) {
				Socket s = ss.accept();
				//这是new出来的一个线程。里面是一个new runnable的方法内部类。
				new Thread(new Runnable() {
					DataInputStream dis = null;
					DataOutputStream dos = null;
					Scanner sc = new Scanner(System.in);
					//重写里面的run方法。
					@Override
					public void run() {
						try {
							dos = new DataOutputStream(s.getOutputStream());
							dis = new DataInputStream(s.getInputStream());
							while (true) {
								String msg = Thread.currentThread().getName()+dis.readUTF();
								System.out.println(msg);
								dos.writeUTF(sc.next());
							
							}
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}finally{if (dos != null)
							try {
								dos.close();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}}
					}
					//这里省略了,直接就start了
				}).start();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

	}

主要是改一下服务器的代码就行了。跟上面的对比就多加了多线程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值