TCP通信与UDP通信
????? TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,只能用于点对点的通讯。TCP提供的是一种可靠的数据流服务,采用差错重传技术来实现传输的可靠性。TCP还进行流量控制,从而限制了发送方的发送速度。封好的TCP数据包将向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送,设备驱动程序和物理介质,最后到接收方。是一个不断打包,包上加包,再不断拆包,一层接一层的拆解。类似,我们邮寄的包裹,通常都是一层一层的加包,对方收到时再一层一层的拆包。包上写有相应层次的地址信息。
注:所谓“三次握手”是指通过TCP客户机与服务器建立联系时,为了达到安全传输数据和确保连接而进行的三次同步作用的包。第一次发送一个同步消息,对方收到后加上一个确认消息发回同步消息,收到后也发送一个确认消息和同步消息的包。之后可以安全地发送数据了。
????? UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,广播发送消息。由于不需要接收方确认,属于不可靠的传输,可能会出现数据丢失的现象。UDP不保证数据包的顺序、错误检测或重发。由于不像TCP有三次握手的初始化连接,很容易被欺骗,而使得数据被截获。
TCP通信流程:
1、创建服务器对象
2、创建套接字
3、得到连接对象
4、取得输入输出流
5、读写数据
UDP通信流程:
1、创建本地地址对象
2、创建套接字
3、创建连接过程
4、创建发送\接收数据包对象
5、读写数据
注:两者在创建套接字时,TCP和UDP创建的都是Socket对象,UDP传入的是本地地址,而TCP传入的是服务器地址。TCP的连接过程,要服务器不断监听指定端口,accept等待客户端接入(accept是阻塞的),客户端根据服务器端的地址,connect请求建立连接,之后就可以通信了。而UDP的连接则简单些,服务器端和本地地址绑定,客户端再和服务器端地址绑定,就可以通信了。
?
我的TCP的例子:
import java.net.Socket;import javax.swing.JTextArea;import javax.swing.JTextField;public class clientTread extends Thread {private Socket sli;private clientUI cli;private java.io.OutputStream ous;private JTextField jtf;private JTextArea jta;public static String name = "client";private String h;public clientTread(Socket sli, clientUI cli, JTextField jtf, JTextArea jta) {this.cli = cli;this.sli = sli;this.jta = jta;this.jtf = jtf;}public void run() {try {// 得到输入输出流java.io.InputStream ins = sli.getInputStream();ous = sli.getOutputStream();// 读取服务器传入的提示字符String inputs = this.serverRead(ins);jta.append("服务器说:" + inputs + "\n");while (!cli.endkey) {if (cli.haveName) {inputs = this.serverRead(ins);} else {System.out.println("name:" + name);// 读写数据inputs = this.serverRead(ins);while (!inputs.equals(null) && (!inputs.equals("end#"))) {// 客户端读入(字符串式读入)h = "服务器" + " says:" + inputs;System.out.println("从服务器读了" + h);if (!h.equals("#")) {jta.append(h + "\n");}inputs = this.serverRead(ins);}h = "结束会话" + "\r\n";// 写出字符cli.sendkey = true;this.sendMessage(h);jta.append(h + "\n");// 客户端关闭sli.close();System.out.println("ins closed!");}}} catch (Exception e) {e.printStackTrace();}}/** * 客户端读入字节,以字符串形式输出 * * @param ins * 传入输入流 * @return 返回客户端发送的字符串 */public String serverRead(java.io.InputStream ins) {try {// 创建一个字符串缓冲区java.lang.StringBuffer input = new java.lang.StringBuffer();int t = 0;while (t != 13 && (t != 35)) {t = ins.read();char c = (char) t;input.append(c);// 将读入的字符放入到字符串缓冲区}String temp = input.toString().trim();return temp;} catch (Exception e) {e.printStackTrace();}return "";}// 写出字符串的方法public void sendMessage(String msg) {try {if (cli.sendkey) {ous.write((msg + "#").getBytes());}// 强制输出ous.flush();} catch (Exception e) {e.printStackTrace();}}}?
/** * 客户端开启并连接服务器 * @param ip 服务器ip地址 * @param port 服务器端口号 */public void clintCreat(String ip,int port,JTextField jtf,JTextArea jta){ try { java.net.Socket sli=new java.net.Socket(ip,port); System.out.println("Hold on>>>>>>>>>>>>"); //开启一个线程用于处理 clientc=new clientTread(sli,this,jtf,jta); clientc.start(); } catch (Exception e) { e.printStackTrace(); } }}
?服务器端:
package telnet3;import java.io.IOException;public class serverCreat{public static void main(String[] args){serverCreat ccreate=new serverCreat(9090);}public serverCreat(int port){try {//创建服务器对象//int port=90;java.net.ServerSocket clint=new java.net.ServerSocket(port);System.out.println("Create a Server successfully!");while(true){//监听,待机状态java.net.Socket cli=clint.accept();//得到连接请求的对象//开启一个线程用于处理serverC serverc=new serverC(cli);serverc.start(); //关闭服务器 //clint.close();}} catch (Exception e) {e.printStackTrace();}}}?
import java.net.ServerSocket;import java.net.Socket;import com.sun.corba.se.spi.orbutil.fsm.Input;public class serverC extends Thread {Socket cli;private java.io.OutputStream ous;public serverC(Socket cli) {this.cli = cli;}public void run() {try {// 得到输入输出流java.io.InputStream ins = cli.getInputStream();ous = cli.getOutputStream();this.sendMessage("May I have your name,please?");System.out.println("eeeeeeeee");String name = this.serverRead(ins);System.out.println("client's name is:" + name);//读写数据String h = "Welcome!" + name;this.sendMessage(h);System.out.println(h);String inputs = this.serverRead(ins);// 服务器读入(字符串式读入)while (!inputs.equals("end#")) {// 当输入的不是end#时,继续读h = /*name + " says:" +*/ inputs;this.sendMessage(h);inputs = serverRead(ins);}// 当输入send#时h = "结束会话" + "\r\n";// 写出字符this.sendMessage(h);System.out.println(h);// 客户端关闭cli.close();System.out.println("ins closed!");// 客户端关闭socket// cli.close();} catch (Exception e) {e.printStackTrace();}}/** * 服务器读入字节,以字符串形式输出 * * @param ins * 传入输入流 * @return 返回客户端发送的字符串 */public String serverRead(java.io.InputStream ins) {try {// 创建一个字符串缓冲区java.lang.StringBuffer input = new java.lang.StringBuffer();int t = 0;while (t != 13 && (t != 35)) {t = ins.read();char c = (char) t;System.out.print("c:" + c + " ");input.append(c);// 将读入的字符放入到字符串缓冲区} System.out.println("读入"+input.toString());return input.toString().trim();} catch (Exception e) {e.printStackTrace();}return "";}// 写出字符串的方法public void sendMessage(String msg) {try {ous.write((msg + "#").getBytes());// 强制输出ous.flush();} catch (Exception e) {e.printStackTrace();}}}?
?