`
hmeng
  • 浏览: 15830 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

socket通信

阅读更多
      前段时间学习了通信机制,小组做了一个仿QQ的聊天工具,能登录,注册,加好友,私聊,群聊,能玩通信游戏。我完成的任务一个你画我猜的通信游戏的模块,并完成了测试。
     本文主要叙述socket的通信机制,关于你画我猜这个模块后续再写出来,这里贴的代码是我完成的模块代码中截取出来的,只为了体现逻辑思路,连贯性可能欠缺请见谅。
     我们在局域网下进行socket通信,首先建立一个本机的服务器,监听端口,等待访问,当有客户端访问时,交给服务端线程处理;然后当客户端对象访问服务器时,客户端线程处理客户端的操作,通过TCP/ip协议与服务端通信。

     下面先介绍一些术语:
     TCP/IP协议是一种面向连接的,可靠的网络传输协议,比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。而UDP协议是非面向连接的协议,就是在正式通信前不必与对方先建立连接,例如你在发短信的时候,只需要输入对方手机号就OK了。
      一个TCP连接必须要经过三次“对话”才能建立起来,这三次对话的简单过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
      我们要确认网络上的每一台计算机,靠的就是能唯一标识该计算机的网络地址,这个地址就叫做IP。在Internet里,IP地址是一个32位的二进制地址,为了便于记忆,将它们分为4组,每组8位,由小数点分开,用四个字节来表示,而且,用点分开的每个字节的数值范围是0~255,如202.116.0.1。
       socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。

      接下来用代码进行说明:
     1、服务端:首先建立一个ServerSocket服务器端口号,当有客户端访问时,交给服务端线程处理。

public class Server {//服务端
	public void setup(int port){
	    try {
	    	//绑定服务器端口号
			ServerSocket sers = new ServerSocket(port);
			System.out.println("服务器监听端口"+port+"成功!");
			
			while(true){
				//等待客户端访问
				Socket socket = sers.accept();
				System.out.println("有人访问!");
				
				//把客户端交给线程处理
				SocketThread st = new SocketThread(socket);
				st.start();
			}			
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}	
	public static void main(String[] args) {
		new Server().setup(6666);

	}

    服务端线程:得到连接入socket的一个输入输出流,Output写数据送到客户机,Input读取数据到服务器,自定义通信协议,根据接受数据包的不同类型进行不同处理。线程类中的run方法以及部分想客户端发送消息的方法如下,更多的向客户端发送不同类型数据的方法不再赘述:
public void run() {
		try {
			// 读取客户端发送的消息

			input = socket.getInputStream();

			DataInputStream dis = new DataInputStream(input);
			// 向客户端发送的消息
			output = socket.getOutputStream();
			dos = new DataOutputStream(output);
			// 输入名字
			String str = "请输入你的名字:\r\n";
			// 服务器向客户端发送消息
			sendMessage(str);
			// 读取客户端输入的名字
			name = readLine(input);
			String name2 = name + "(" + socket.getInetAddress() + ")";
			System.out.println("name:" + name2);
			// 从客户端读取字符串消息
			while (true) {
				// 接受数据包的类型
				int type = dis.readInt();
				if (type == 1) {
					// 接收数据包的长度
					int len = dis.readInt();
					byte[] bytes = new byte[len];
					dis.readFully(bytes);
					// 读取客户端的输入流字符串
					String line = new String(bytes, "GBK");

					if ("bye\n".equals(line)) {
						System.out.println("服务器收到 " + name + "已下线!");
						break;
					}
					// 打印当前客户所说的话
					System.out.println("服务器收到 " + name + ":" + line + "======");
                    System.out.println(keyWord+"\n======");
					if (line.equals(keyWord + "\n")) {//判断对方是否猜对
						System.out.println("猜对了!");
						for (int i = 0; i < list.size(); i++) {
							SocketThread st = list.get(i);
							// 向其他客户端发出消息
							st.sendMessage(name + "猜对了!\n");
							st.sendAccess("good");
						}
						sendTitle();

					}

					// 群发消息
					for (int i = 0; i < list.size(); i++) {
						SocketThread st = list.get(i);
						if (st == this) {
							continue;
						}
						// 向其他客户端发出消息
						String msg = name + ":" + line;
						st.sendMessage(msg);

					}
				} else if (type == 2) {
					// 接收画图信息
					int len = dis.readInt();
					int x1 = dis.readInt();
					int y1 = dis.readInt();
					int x2 = dis.readInt();
					int y2 = dis.readInt();
					int r = dis.readInt();
					int g = dis.readInt();
					int b = dis.readInt();
					Color c = new Color(r,g,b);
					// 群发消息
					for (int i = 0; i < list.size(); i++) {
						// System.out.println("群发");
						SocketThread st = list.get(i);
						// 向其他客户端发出画图消息
						st.sendDraw(x1, y1, x2, y2,c);

					}
				} else if (type == 3) {
					if (list.size() <= 1) {
						return;
					}
					// 发送题目
					sendTitle();
				} else if (type == 4) {
					// 群发清屏消息
					for (int i = 0; i < list.size(); i++) {
						SocketThread st = list.get(i);
						// 向所有客户端发出画图消息
						st.sendClear();
					}
				} else if (type == 5) {
					// 接收数据包的长度
					int len = dis.readInt();
					byte[] bytes = new byte[len];
					dis.readFully(bytes);
					// 读取客户端的输入流字符串
					String line = new String(bytes, "GBK");
					// 给画图者发送评价消息
					drawst.sendAccess(line);

				}
			}
			// 客户下线关闭当前端口
			socket.close();
			// 删除队列中的对象
			list.remove(this);

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

/*
	 * 读取输入流的方法
	 */
	private String readLine(InputStream input) throws IOException {
		// 新建一个字节队列
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataInputStream dis = new DataInputStream(input);
		dis.readInt();
		dis.readInt();
		while (true) {
			int n = input.read();
			// System.out.println(n);
			// 回车符
			if (n == '\r') {
				continue;
			}
			// 换行符
			if (n == '\n') {
				break;
			}
			// 把读取的字节内容先保存
			bos.write(n);
		}
		// 把字节队列中的数据取出来
		byte[] bytes = bos.toByteArray();
		String content = new String(bytes, "GBK");
		return content;
	}

	/*
	 * 向客户端发送消息的方法
	 */
	public void sendMessage(String msg) {
		try {
			// 服务器输出流写入字节
			byte[] bytes = msg.getBytes();
			int len = bytes.length;
			dos.writeInt(1);
			dos.writeInt(len);
			dos.write(bytes);
			dos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	 * 向客户端发送画图线段消息的方法
	 */
	public void sendDraw(int x1,int y1,int x2,int y2,Color color){
		try {
			//客户端输出流写入字节	
			dos.writeInt(2);
			dos.writeInt(28);
			dos.writeInt(x1);
			dos.writeInt(y1);
			dos.writeInt(x2);
			dos.writeInt(y2);
			int red = color.getRed();
			int green = color.getGreen();
			int blue = color.getBlue();
			dos.writeInt(red);
			dos.writeInt(green);
			dos.writeInt(blue);
			dos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

     2、客户端:创建一个客户端窗体,并初始化界面,然后启动客户端线程处理。这部分比较简单不贴代码。
       客户端线程:创建对应服务端的socket套接字,连接服务器,根据通信协议,依不同的数据包类型进行处理,run方法如下

public void run (){
		try{
			System.out.println("连接服务器......");
			Socket socket = new Socket("127.0.0.1",6666);
			System.out.println("成功!");
			//读取对方发送的消息
			InputStream input = socket.getInputStream();
			DataInputStream dis = new DataInputStream(input);
			//向对方发送的消息
			output = socket.getOutputStream();
			dos = new DataOutputStream(output);			
			while(true){
				//接受数据包的类型
				int type=dis.readInt();
				if(type==1){
					//接收数据包的长度
					int len = dis.readInt();
					byte[] bytes= new byte[len];
					dis.readFully(bytes);
					//读取客户端的输入流字符串
					String line = new String(bytes,"GBK");
//					System.out.println(line);
					//從服务器接收到的消息显示到界面上
					l.onRecvMsg(line);

				}else if(type == 2){
					//接收画图信息
					int len = dis.readInt();
					int x1 = dis.readInt();
					int y1 = dis.readInt();
					int x2 = dis.readInt();
					int y2 = dis.readInt();
					int r = dis.readInt();
					int g = dis.readInt();
					int b = dis.readInt();
					Color c = new Color(r,g,b);
					l.onDraw(x1, y1, x2, y2,c);
				}else if(type==3){
					//从服务端接受画图题目信息
					int len = dis.readInt();
					byte[] bytes= new byte[len];
					dis.readFully(bytes);
					//读取客户端的输入流字符串
					String str = new String(bytes,"GBK");
					l.onTitle(str);
				}else if(type == 4){
					//清屏
					l.onclear();
				}else if (type == 5) {
					// 接收数据包的长度
					int len = dis.readInt();
					byte[] bytes = new byte[len];
					dis.readFully(bytes);
					// 读取客户端的输入流字符串
					String line = new String(bytes, "GBK");
					// 给画图者增加评价消息
					l.onAccess(line);

				}
				
				
			}
		}catch (Exception e){
			System.out.println("失败!");
			e.printStackTrace();
		}
	}
其中在接受到服务端数据之后,对客户端界面处理的方法通过客户端类实现接口MsgListener来完成,这样做能使代码的设计更合理,模块之间调用更加方便。
public interface MsgListener {
	//在日志上显示消息
	public void onRecvMsg(String str);
	//在画图区上画图
	public void onDraw(int x1,int y1,int x2,int y2,Color color);
	//显示题目
	public void onTitle(String str);
	//清屏
	public void onclear();
	//显示评价
	public void onAccess(String access);
}

测试截图:

  • 大小: 173.9 KB
分享到:
评论

相关推荐

    C#Socket通信稳定完整版类库实例

    Socket通信在IT行业中是网络编程的基础,特别是在C#这样的多平台开发环境中,Socket通信库的使用至关重要。本实例,"C# Socket通信稳定完整版类库实例",为我们提供了一个全面且稳定的解决方案,用于实现客户端与...

    windows下socket通信代码

    在Windows环境下进行网络编程时,Socket通信是一种常用的技术。Socket接口是操作系统提供的网络通信API,允许应用程序通过TCP/IP协议栈与其他计算机进行数据交换。本文将详细介绍Windows下的Socket通信代码,包括...

    c++ socket通信库

    **C++ Socket通信库** C++ Socket通信库是用于实现网络通信的一种工具,它基于操作系统提供的Socket接口,为开发者提供了一种在C++程序中进行网络数据交换的标准方法。Socket库简化了网络编程,允许程序员通过调用...

    Android中socket通信简单实现

    Android中socket通信简单实现 socket通信需要有一个服务器和客户端,可以把同一个APP作为服务器跟客户端,也可以分开成两个APP。 先上个图: 这里以一个APP作为服务器跟客户端为示例 1、添加网络访问权限 2、写...

    Mina+Socket通信

    Socket通信的基本步骤包括:创建ServerSocket,等待客户端连接,创建Socket对象,通过输入/输出流进行数据交换,最后关闭连接。 在Mina与Socket通信的实现中,服务端通常使用Mina来创建一个Acceptor,监听特定端口...

    matlab环境下socket通信

    在MATLAB环境中实现Socket通信是将强大的MATLAB计算能力与网络通信功能相结合的重要技术。Socket是一种网络编程接口,它允许程序之间通过网络进行双向通信。MATLAB提供了丰富的工具和函数来支持Socket通信,使得用户...

    C#与Android Socket通信

    Socket通信是一种基于TCP/IP协议族的网络通信方式,它允许两个网络应用程序通过网络进行数据交换。在本场景中,我们关注的是C#作为服务器端,Android作为客户端的Socket通信实现。这种通信方式常用于移动应用与后台...

    socket通信,客户端向服务器传文件

    在IT领域,Socket通信是一种基于TCP/IP协议族的网络编程接口,用于实现不同网络设备间的双向通信。在Java中,我们可以使用Java的Socket类和ServerSocket类来构建客户端和服务器端的通信。在这个场景中,我们将讨论...

    android+pc socket通信

    "Android+PC Socket通信"指的是通过TCP Socket协议实现Android设备(手机客户端)与个人计算机之间的数据传输。Socket通信允许应用程序之间建立端到端的连接,进行双向数据交换,非常适合用于实时通讯、文件传输等...

    Android socket通信聊天,客户端+服务端

    在Android平台上进行网络通信时,Socket通信是一种常见且重要的方式,尤其在实现聊天应用时。本文将深入探讨如何在Android中实现基于Socket的客户端和服务端通信,以构建一个简单的聊天应用。 首先,让我们理解...

    android中java和C的socket通信demo

    本教程将详细解释如何在Android中实现Java和C的Socket通信,特别是在涉及文件描述符传递的场景下。 1. **Java Socket基础** Java中的`java.net.Socket`类提供了网络通信的能力,它允许我们在两个应用程序之间建立...

    socket通信代码 点到点通信

    Socket通信是一种基于网络协议(如TCP/IP)进行进程间通信的技术,它允许两台计算机通过互联网交换数据。在本文中,我们将深入探讨“点到点通信”中的Socket通信代码,包括服务端和客户端的实现。 首先,让我们了解...

    Socket通信经典源码HPSocketCS

    Socket通信在IT行业中扮演着至关重要的角色,它是网络应用程序间通信的基础。HPSocketCS是一个专为.NET平台设计的高效、稳定的Socket通信框架,适用于开发跨平台的客户端和服务器端应用。本文将深入探讨HPSocketCS的...

    java与c++通过socket通信

    Java和C++之间的Socket通信是跨语言网络编程的一个常见应用场景,尤其在系统集成、设备通讯或者混合编程中。Socket提供了一种基于TCP/IP协议的进程间通信(IPC)方式,可以实现在不同操作系统上的进程之间的数据传输...

    socket通信异常解决总结

    Socket 通信异常解决总结 Socket 通信异常是指在网络通信过程中出现的各种错误和异常,包括网络连接断开、服务器端或客户端程序异常、网络链路异常等。这些异常会导致 Socket 连接断开,影响系统的稳定性和可靠性。...

    C# AES加密Socket通信

    本篇文章将详细探讨C#中如何使用AES加密进行Socket通信,以及涉及的TCP/IP协议。 首先,让我们了解Socket通信的基础。Socket是操作系统提供的网络编程接口,它允许应用程序通过TCP/IP协议发送和接收数据。在C#中,`...

    基于Qt实现局域网Socket通信系统源码.zip

    基于Qt实现局域网Socket通信系统源码。分别有服务端(Server)和客户端(Client) 服务端默认监听本机IP的6666端口 本人实测在linux(需防火墙开启端口)和windows下完美运行。基于Qt实现局域网Socket通信系统源码。...

    linux C语言 socket通信聊天小程序

    本项目涉及的"Linux C语言 socket通信聊天小程序"是一个基础的网络聊天应用,支持群聊和私聊功能。 首先,我们需要理解什么是Socket。Socket是网络编程的一个接口,它提供了进程间通信(IPC)的能力,特别是在网络...

    socket通信文件传输

    Socket通信是一种基于TCP/IP协议族实现的网络通信方式,它允许两台计算机通过网络进行双向通信。在文件传输中,Socket通信提供了一种灵活、高效的方法,尤其适用于大数据量或者跨平台的文件交换。以下是对Socket通信...

    Android基于局域网socket通信

    在Android平台上,实现基于局域网的Socket通信是一项常见的任务,尤其在开发涉及设备间通信的应用时。Socket通信允许两台设备通过网络连接直接交换数据,而无需中间服务器。在这个项目中,我们关注的是Android设备...

Global site tag (gtag.js) - Google Analytics