package cc.leng.tcpip.step1; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; public class TCPEchoServer { private static final int BUFSIZE = 32; public static void main(String[] args) throws Exception { ServerSocket server = null; try{ if((args.length != 1)){ throw new IllegalArgumentException("Parameters(s): <Port>"); } int serverPort = Integer.parseInt(args[0]); server = new ServerSocket(serverPort); int recvMsgSize; byte[] receiveBuf = new byte[BUFSIZE]; while(true){ Socket socket = server.accept(); SocketAddress clientAddr = socket.getRemoteSocketAddress(); System.out.println("Handling client at "+clientAddr+""); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); while((recvMsgSize = in.read(receiveBuf)) != -1){ out.write(receiveBuf, 0, recvMsgSize); } socket.close(); } }finally{ System.out.println(""); } } }
package cc.leng.tcpip.step1; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; public class TCPEchoClient { public static void main(String[] args) throws Exception, IOException { Socket socket = null; try{ if((args.length <2) || (args.length >3)){ throw new IllegalArgumentException("Parameters(s): <Server> <word> [<Port>]"); } String server = args[0]; byte[] data = args[1].getBytes(); int serverPort = args.length == 3 ? Integer.parseInt(args[2]) : 7777; socket = new Socket(server,serverPort); System.out.println("Connected to server ... sending echo string"); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); out.write(data); int totalBytesRcvd = 0; int bytesRcvd; while(totalBytesRcvd < data.length){ if((bytesRcvd = in.read(data, totalBytesRcvd, data.length)) == -1){ throw new SocketException("Connection closed prematurely"); } totalBytesRcvd += bytesRcvd; } System.out.println("Received: "+ new String(data)); }finally{ if(null != socket) socket.close(); } } }
重点:in.read(buf) != -1
问: 什么时候会返回-1
答:对端socket.close();或者socket.shutdownOutput();
问:在while循环中,in.read()如果完成一轮轮询?
答:TCP协议中包头带有对端out.write(buf)的长度,接收端可以通过这个长度来判断这次轮询接收是否结束
上面代码分析
服务端在while循环中反复读取字节数据(数据在可获取时),并立即将同样的字节返回给输出流,这个过程一直持续到客户端关闭连接。INputStream的read()方法每次获取缓存数组所能放下的最多字节(BUFSIZE),并存入该数组(receiveBuf),同时返回实际读取的字节数。read()方法将阻塞带灯,直到有可读数据。如果数据已经读取完成则返回-1,标识客户端关闭了其套接字。在消息反馈时,客户端在接受的字节数与其发送的字节数相等就关闭连接,因此在服务器端最终将从read()方法中收到-1的返回值。(这个地方是已知了数据接收的大小,如果totalBytesRcvd < data.length表示 没有接收完并且通讯就结束了则抛出异常)
下边是引用查找到到TCP连接和数据的原理
Java当中的Socket类,其实是使用TCP协议进行传输的.TCP是可靠的一种传输协议.
如果想用TCP协议,并且,服务端和客户端,在没有信息进行传输的时候,也不断开连接,一般情况下,客户端会在Socket超时之前,想服务端发送一个用于维持连接的信息包,来维持连接.但是TCP协议,并不是指长连接.我们每天上网浏览网页,其实,也是以TCP协议为基本的传输协议的.只是,这个是短连接的形式,每次浏览器向服务器提交一个请求,服务短应答请求,然后断开连接.
在应用TCP协议,并且是长连接传输信息的情况下.通常会再封装一层协议的.但,观察版主的收发内容,并没有涉及这一层,所以,我这里并不知道是长连接.
首先,我们要明确一点,发送方如果不将输出流进行关闭,接收方就会认为输入流没有结束,直到超时.
其次,我们判断一个信息是否已经完全的读取完毕,除了使用输入流结束这种办法,还可以自行封装一层协议,用于信息的交互.
当然,我们也可以采用Http那样的交互方式进行信息的传递,但是,它是短连接的.
下面我来说一下,TCP长连接传输数据的一般做法.
一般情况下,我们会在TCP的基础上再封装一层协议,用户长连接的传输.协议的信息包,也分包头和包体两个部分.
包体,主要就是我们要传输的信息.(维持连接的信息包,包体可为空)
包头,一般分为三个部分.第一部分是信息包的长度(长度一般是指整个信息包的长度);第二部分是包体信息的类型(在这里指出是否是维持连接包);第三部分是信息包的序列号,一般情况下,这个序列号要确保在传输过程中唯一标识该信息包.
如果为了安全起见,还可以在包体后添加包尾,包尾数据用于对包体数据的验证)
这样,通信双方就可以根据包长来判断一次接收的操作是否结束了.
相关推荐
serial tcp/ip 串口通讯
三菱FX5UJ和艾莫迅远程模块实现TCP/IP通讯,程序包含多种功能吗的实现
这个实例是比较完整的TCP/IP可以根据自己的需要进行扩充,包括Server端,和Client端程序
MFC例子TCP/IP通讯技术
用C#写的简单的TCP/IP通信小示例,开发环境为VS2013,里面有一个服务端和一个客户端,适合新手看看
wince 6.0下的TCP/IP通信源码,用于ARM开发板上实现TCP通信,便于初学者熟悉网络通信编程。
包含一个与PLC进行网络通讯和与外部设备进行串口通讯的程序
简单的Android Socket ...客户端通过UDP广播获取到服务器端的IP地址,通过TCP/IP协议与服务器建立连接。代码实现心跳检测,当服务器断网或是结束进程,客户端可重新连接(重连部分自己实现);代码有点凌乱,仅供参考!
如何实现TCP/IP通讯 在C语言的环境下 经典 不容 错过
TCP/IP协议的传输即面向点到点的传输方式!该源码就是通过tcp/ip这种协议做了个简单的客户端和服务器的聊天测试程序,希望对初学者有帮助
基于socket应用的TCP/Ip通讯。包含一个服务端,一个客户端。实现客户端与服务端通讯。
TCP/Ip通讯源代码,可参照该代码,做局域网通讯的vb完整通讯,有一定的借鉴作用
计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都...
用TCP/IP服务器客户端通讯源代码(基于VC++) 网络通讯相关,供大家学习
pb下使用tcp/ip协议通讯
比较详细的介绍了编写tcp/ip的通讯程序,重点讲解了各个组件的属性,方法,非常适用于初学者
本程序示例二台计算机如何通过Tcp/Ip方式进行点对点通讯。
TCP/IP通讯实例源代码(服务端和客户端源码)将socket消息设置为窗口接收的消息类型!
C#写的与PLC通过TCP/IP协议通信的实例,代码供参考 C#写的与PLC通过TCP/IP协议通信的实例,代码供参考
基于MFC的TCP/IP的socket源码编程。