发送数据的格式和应用协议。
一旦双方建立了TCP连接,连接中的任何一方都能向对方发送数据并接收对方发来的数据。
发送数据时,程序员可以编写程序不断地将数据流写入TCP的发送缓冲区中,然后TCP自动从发送缓冲区中取出一定量的数据流写入TCP的发送缓冲区中,然后TCP自动从发送缓冲区中取出一定量的数据,将其组成TCP报文段逐个发送给IP层,再通过IP层发送出去。
接收端从IP层收到TCP报文段后,将其暂时保存在接收缓冲区中,这时程序员就可以编写程序依次读取接收缓冲区中的数据,从而达到通信的目的。
扩展资料
利用TcpClient和TcpListener在同步方式下接收、发送数据及监听客户端连接时,在 *** 作没有完成之前一直处于阻塞状态,这在接收、发送数据量不大或者 *** 作用时较短的情况下是比较方便的。
但是,对于那些完成时间可能较长(如传送大文件)的任务时,使用同步 *** 作可能就会造成系统假死,这种情况下,最好的办法是使用异步 *** 作。
服务器端可以采用多线程处理客户请求,例如:package threadPool;
import javaioBufferedReader;
import javaioIOException;
import javaioInputStream;
import javaioInputStreamReader;
import javaioOutputStream;
import javaioPrintWriter;
import javanetServerSocket;
import javanetSocket;
import javautilconcurrentExecutorService;
import javautilconcurrentExecutors;
public class ThreadPoolServer {
private int port = 8000;
private ServerSocket serverSocket;
private ExecutorService executorService; //线程池
private final int POOL_SIZE = 4; //单个CPU时线程池中的工作线程数目
public ThreadPoolServer() throws IOException{
serverSocket = new ServerSocket(port);
//创建线程池
//Runtime 的availableProcessors()方法返回当前系统CPU的数目
//系统CPU越多,线程池中的工作线程数目越多
executorService = ExecutorsnewFixedThreadPool(RuntimegetRuntime()availableProcessors()POOL_SIZE);
Systemoutprintln("服务器已启动!!");
}
public void service(){
while(true){
Socket socket = null;
try{
socket = serverSocketaccept();
executorServiceexecute(new Handler(socket));
}catch(IOException e){
eprintStackTrace();
}
}
}
public static void main(String[] args) {
try {
new ThreadPoolServer()service();
} catch (IOException e) {
eprintStackTrace();
}
}
}
class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
thissocket = socket;
}
private PrintWriter getWriter(Socket socket) throws IOException {
OutputStream socketOut = socketgetOutputStream();
return new PrintWriter(socketOut, true);
}
private BufferedReader getReader(Socket socket) throws IOException {
InputStream socketIn = socketgetInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}
public String echo(String msg) {
return "echo:" + msg;
}
@Override
public void run() {
try {
Systemoutprintln("New connection accepted:" + socketgetInetAddress() + ":" + socketgetPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = brreadLine()) != null) {
Systemoutprintln(msg);
pwprintln(echo(msg));
if (msgequals("bye")) {
break;
}
}
} catch (IOException e) {
eprintStackTrace();
} finally {
try {
if (socket != null)
socketclose();
} catch (IOException e) {
eprintStackTrace();
}
}
}
}我打比喻你就理解了。就像我们去买包子一样。我们是客户端,卖包子的老板就是服务器。为了避免每来个客人买包子(发送请求)都要做个新包子,引起每个客户都要等一段时间,一般老板会先预先做好几个包子放在蒸笼里。而这预先做好的包子我们称为连接对象,存在包子的蒸笼称为线程池。线程池的作用就是预先保存一些连接对象。避免每次客户请求都要去创建新的连接而浪费不必要的时间。可以提高请求的性能和质量。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)