利用Socket进行CS间通信

利用Socket进行普通通信
  • TCP:(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议.

  • UDP:(UDP,User Datagram Protocol)无连接的协议,在传输数据之前,客户端和服务器端不建立和维护连接,提供不可靠的数据传输。

  • Socket(套接字):基于TCP协议的网络通信,可以提供双向安全连接的网络通信。Socket利用数据流来完成数据的传递工作。

  • 使用步骤:
    1.建立连接
    2.通过Socket生成InputStream/OutputStream(准备发送数据)
    3.使用InputStream/OutputStream进行发送数据和接收数据
    4.关闭InputStream、OutputStream、Socket

  • 服务端代码

package org.dsl.socketDome;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class MyService {
	public static void main(String[] args) {
		ServerSocket serverSocket = null;
		Socket accept = null;
		InputStream in = null;
		BufferedReader reader = null;
		OutputStream out = null;
		
		try {
			//接收连接
			serverSocket = new ServerSocket(8080);
			System.out.println("准备连接。。。。");
			accept = serverSocket.accept();
			System.out.println("服务端接收到连接");
			in = accept.getInputStream();
			//利用转换流:字节流-->转换流-->字符流,如果不使用BufferedReader字符流,
			//则需要定义缓冲数组(字节缓冲或者字符缓冲)用来接收数据
			reader = new BufferedReader(new java.io.InputStreamReader(in));
			String str = null;
			while ((str = reader.readLine())!=null) {
				System.out.println(str);	
			}
			accept.shutdownInput();
			//发出数据
			out = accept.getOutputStream();
			out.write("欢迎访问服务器".getBytes());
			accept.shutdownOutput();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(out!=null) out.close();
				if(reader!=null)reader.close();
				if(in!=null)in.close();
				if(accept!=null)accept.close();
				if(serverSocket!=null)serverSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

  • 客户端代码
package org.dsl.socketDome;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class MyClient {
	public static void main(String[] args) {
		Socket socket = null;
		OutputStream out = null;
		InputStream in = null;
		BufferedReader reader = null;
		
		
		try {
			//建立连接
			socket = new Socket("127.0.0.1",8080);
			//发送数据
			out = socket.getOutputStream();
			out.write("hello server".getBytes());
			socket.shutdownOutput();
			//接收数据
			in = socket.getInputStream();
			reader = new BufferedReader(new java.io.InputStreamReader(in));
			String str = null;
			while ((str=reader.readLine())!=null) {
				System.out.println(str);	
			}
			socket.shutdownInput();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {			
				try {
					if(out!=null)out.close();
					if(socket!=null)socket.close();
					if(reader!=null)reader.close();
					if(in !=null)in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}

		
	}
   
}

  • 特别关注

    1.服务端代码使用ServerSocket类(底层还是产生Socket类的对象)来产生对象,并且调用accept()方法来进行拦截客户端的通信请求,进行实时通信。
    2.客户端代码是利用Socket类来产生对象,进行通信的。
    3.需要利用shutdownOutput()、shutdownIutput()在输入输出后,作用是先前写入的数据将被发送后正常关闭TCP连接,如果不写则通信将不会把信息成功传输。
    4.在程序的最后要进行,将流关闭,原则:先写后关,先关外,再关内。

利用Socket进行对象通信
前提条件
  • 实体类必须实现Serializable进行序列化;
  • 信息的收发必须使用对象流ObjectOutputStream/ObjectIutputStream。
  • 实体类代码
package org.dsl.objectSocket;

import java.io.Serializable;

public class Student implements Serializable {
	private String name;
	private int sex;
	private int age;

	public Student() {

	}

	public Student(String name, int sex, int age) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getSex() {
		return sex;
	}

	public void setSex(int sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}

}

  • 服务端代码:
package org.dsl.objectSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class myServer {
	public static void main(String[] args) {
		ServerSocket serverSocket = null;
		Socket socket =null;
		InputStream in = null;
		ObjectInputStream object = null;
		try {
			//建立连接
			serverSocket = new ServerSocket(8080);
			socket = serverSocket.accept();
			System.out.println("服务端接收到连接");
			//利用socket建立InputStream/OutputStream
			in = socket.getInputStream();
			//利用转换流将字节流,装换为对象流
			object = new ObjectInputStream(in);
			//装换为Student类
			Student student = (Student)object.readObject();
			System.out.println("接收到的数据:"+student);
			//进行关闭操作
			socket.shutdownInput();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(object!=null)object.close();
				if(in!=null)in.close();
				if(socket!=null)socket.close();
				if(serverSocket!=null)serverSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

  • 客户端代码:
package org.dsl.objectSocket;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class myClient {
	public static void main(String[] args) {
		Socket socket = null;
		OutputStream out = null;
		ObjectOutputStream object = null;
		try {
			// 进行连接
			socket = new Socket("localhost", 8080);
			// 创建对象
			Student student = new Student("zs", 1, 20);
			out = socket.getOutputStream();
			// 将字节流对象转换为对象流
			object = new ObjectOutputStream(out);
			System.out.println("准备将对象发送。。。。");
			object.writeObject(student); 
			System.out.println("对象发送完毕!");
			// 进行关闭
			socket.shutdownOutput();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {

			try {
				if (object != null)object.close();
				if(out!=null)out.close();
				if(socket!=null)socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

利用多线程实现多个客户端访问服务器
  • 服务器端代码
package org.dsl.threadSocket;

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

public class MyServer {
	public static void main(String[] args) {
		ServerSocket serverSocket = null;
		Socket socket = null;
		try {
			serverSocket = new ServerSocket(8080);
			while(true) {
				socket = serverSocket.accept();
				ThreadServer threadServer = new ThreadServer(socket);
				threadServer.start();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(socket!=null)socket.close();
				if(serverSocket!=null)serverSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

  • 多线程端代码
package org.dsl.threadSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ThreadServer extends Thread{
	Socket socket;
	InputStream in = null;
	ObjectInputStream ois = null;
	OutputStream out = null;

	public ThreadServer(Socket socket) {
		super();
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			in = socket.getInputStream();
			ois = new ObjectInputStream(in);
			Student student = (Student)ois.readObject();
			System.out.println(student);
			socket.shutdownInput();
			//接收成功返回信息
			out = socket.getOutputStream();
			out.write("成功接收到数据。。。".getBytes());
			socket.shutdownOutput();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				if(out!=null)out.close();
				if(ois!=null)ois.close();
				if(in!=null)in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}

  • 客户端一代码
package org.dsl.threadSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class myClient {
	public static void main(String[] args) {
		Socket socket = null;
		OutputStream out = null;
		ObjectOutputStream object = null;
		try {
			// 进行连接
			socket = new Socket("localhost", 8080);
			// 创建对象
			Student student = new Student("zs", 1, 20);
			out = socket.getOutputStream();
			// 将字节流对象转换为对象流
			object = new ObjectOutputStream(out);
			System.out.println("准备将对象发送。。。。");
			object.writeObject(student); 
			System.out.println("对象发送完毕!");
			// 进行关闭
			socket.shutdownOutput();
			//接收服务器返回结果
			InputStream in = socket.getInputStream();
			byte[] buf = new byte[100];
			in.read(buf);
			System.out.println("服务端返回:"+new String(buf));
			socket.shutdownInput();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {

			try {
				if (object != null)object.close();
				if(out!=null)out.close();
				if(socket!=null)socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

  • 客户端二代码:
package org.dsl.threadSocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class myClient2 {
	public static void main(String[] args) {
		Socket socket = null;
		OutputStream out = null;
		ObjectOutputStream object = null;
		try {
			// 进行连接
			socket = new Socket("localhost", 8080);
			// 创建对象
			Student student = new Student("lisi", 0, 21);
			out = socket.getOutputStream();
			// 将字节流对象转换为对象流
			object = new ObjectOutputStream(out);
			System.out.println("准备将对象发送。。。。");
			object.writeObject(student); 
			System.out.println("对象发送完毕!");
			// 进行关闭
			socket.shutdownOutput();
			//接收服务器返回结果
			InputStream in = socket.getInputStream();
			byte[] buf = new byte[100];
			in.read(buf);
			System.out.println("服务端返回:"+new String(buf));
			socket.shutdownInput();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {

			try {
				if (object != null)object.close();
				if(out!=null)out.close();
				if(socket!=null)socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

  • 特别关注
    利用线程实现多客户端访问服务器,实际的收发信息是在线程中的run()方法中实现的,需要借助有参构造器实现多个socket的分配。
使用DatagramSocket实现UDP协议
  • UDP的通信是要依靠DatagramPacket和DatagramSocket对象来实现的,DatagramPacket是类似于装载信息的“箱子”,而DatagramSocket是获取数据的手段,发送数据时,需要先定义DatagramPacket“箱子”,其中箱子要有数据才可以,通过DatagramSocket将数据发送出去;在接收数据时,也需要先定义DatagramPacket“箱子”,再定义DatagramSocket对象,利用DatagramSocket对象将数据拿到,然后在装入DatagramPacket箱子中,在之后的代码实际上都是使用DatagramPacket对象进行操作的。
  • UDP是无连接的通信,所以无需象TCP通信时,将所有对象全部关闭才可以,只需要关闭DatagramSocket对象即可。
  • 服务器端代码:
package org.dsl.udpdemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class MyServer {
	public static void main(String[] args) {
		DatagramPacket dp = null;
		DatagramSocket ds = null;
		try {
			//定义字节缓冲数组
			byte[] data = new byte[64];
			//
			dp = new DatagramPacket(data,data.length);
			ds = new DatagramSocket(8080);
			//将接收的数据放入dp中
			ds.receive(dp);
			//显示接收数据
			String str = new String (dp.getData(),0,data.length);
			System.out.println("接收返回数据:"+str);
			System.out.println("发送方地址:"+dp.getAddress().getHostAddress());
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			ds.close();
		}
	}

}

  • 客户端代码:
package org.dsl.udpdemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class MyClient {
	public static void main(String[] args) {
		DatagramPacket dp = null;
		DatagramSocket ds = null;

		try {
			String msg = "hello...";
			InetAddress byName;
			byName = InetAddress.getByName("127.0.0.1");
			dp = new DatagramPacket(msg.getBytes(),0,msg.length(),byName,8080);
		    ds = new DatagramSocket();
			ds.send(dp);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			ds.close();
		}
		
	}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值