计算机网络相关的问题,如果想去了解,前提就是深刻理解网络4/7层模型。
记住并理解,上面每一层。切记,切记,切记。知道一些就可以开始主题,分两个部分TCP和Socket。
TCP是(Tranfer Control Protocol)的简称,在OSI参考模型第四层,也就是端口,到端口的的通信,它是一个可靠的双向连接,一旦建立连接就可以双向数据传输,双方都可以进行发送或接收 *** 作。
最常听说的就是三次握手。是的它说的就是TCP建立连接的过程。具体的步骤如下:
第一步:Server监听端口,状态为:Listen
第二部:Client发送SNY包,请求连接,并将状态改为:SYN_SEND
第三部:Server发送ACK包,和SNY包,同意,并请求连接,状态改为:SYN_RCVD
第四部:Client发送ACK包,Server收到包后,连接建立。双方状态改为:ESTABLISHED
第一步:Client发起FIN包。状态变为:FNI_WAIT_1
第二步:Server发送ACK包。状态变为:CLOSE_WAIT,Client收包后状态变为:FNI_WAIT_2
第三步:Server发送FIN包,状态变为:LAST_ACK。Client收包后状态变为:TIME_WAIT
第四步:Client发送ACK包。双方状态变为:CLOSED
需要注意的是,Client是在收到Server FIN包后两个最大报文时间(2MSL)后变为CLOSED状态的。双方都可以发起断开请求,上面是已先发起请求的是Client。
如何验证上面讲的这些呢?那就是抓包分析,其实日常的开发中也可以通过抓包来发现问题。在这里我简单贴个图看一下TCP的包,这个工具非常强大感兴趣的朋友可以去深入了解一下。
1可以在这个过滤,通过协议,通过IP,通过端口都可以。
2这个就是每个包,例子中的这个是个[SYN,ACK]包,就是建立TCP连接的第二次握手
3被抓取的包对应的网络层,从上到下分别是:物理层、数据链路层、网络层、传输层。
Socket其实就是TCP协议的实现。也就是说它就是TCP的API,当然其实Socket也支持别的协议如:UDP。既然是API那,上面说的其实就是它的原理。下面说一下它的使用。大概说一下。
1ServerSocket:是服务端来监听的类。监听方法accept()。
2客户端:创建Socket对象,设定IP和Port
3当有新的客户端连接时可以通过ServerSocket类获取Socket。而Socket就是我们的通讯渠道。
4发送和读取数据分别使用OutputStream和InputStream而这两个类是从Socket获取的。
其实Socket的基本使用就是这么简单,但是在其实项目中这样是无法满足需求的。实际上大多数场景都是需要一对多的提供服务。
使用多线程实现多客户端的通信
实现服务器与多个客户端进行通信, 可以接受多个客户端的请求并进行回复
应用多线程来实现服务器与多客户端之间的通信
1、服务器端创建ServerSocket,循环调用accept()等待客户端连接
2、客户端创建一个Socket并请求和服务器端连接
3、服务器端接受客户端请求,创建socket与该客户建立专线连接
4、建立连接的两个socket在一个单独的线程上对话
5、服务器端继续等待新的连接
这种东西,Google下大把吧,正好前阵子有一个TCP通讯的,借你参考下好了:
Server Side
package nio;
import javaioByteArrayOutputStream;
import javaioIOException;
import javanetInetSocketAddress;
import javanetServerSocket;
import javanioByteBuffer;
import javaniochannelsSelectionKey;
import javaniochannelsSelector;
import javaniochannelsServerSocketChannel;
import javaniochannelsSocketChannel;
import javatextDateFormat;
import javatextSimpleDateFormat;
import javautilDate;
public class EchoServer {
private static int SOCKET_NUM = 55555;
private static DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
/
@param args
/
public static void main(String[] args) {
new EchoServer()start();
}
public void start() {
try {
Selector selector = bindServer(); // 绑定服务端口,并定义一个事件选择器对象记录套接字通道的事件
/ 通过此循环来遍例事件 /
while (true) {
log("Waiting events");
int n = selectorselect(); // 查询事件如果一个事件都没有,这里就会阻塞
log("Got events: " + n);
ByteBuffer echoBuffer = ByteBufferallocate(50); // 定义一个byte缓冲区来存储收发的数据
/ 循环遍例所有产生的事件 /
for (SelectionKey key : selectorselectedKeys()) {
SocketChannel sc;
selectorselectedKeys()remove(key); // 将本此事件从迭带器中删除
/ 如果产生的事件为接受客户端连接(当有客户端连接服务器的时候产生) /
if ((keyreadyOps() & SelectionKeyOP_ACCEPT) == SelectionKeyOP_ACCEPT) {
ServerSocketChannel subssc = (ServerSocketChannel) keychannel(); // 定义一个服务器socket通道
sc = subsscaccept(); // 将临时socket对象实例化为接收到的客户端的socket
scconfigureBlocking(false); // 将客户端的socket设置为异步
scregister(selector, SelectionKeyOP_READ); // 将客户端的socket的读取事件注册到事件选择器中
Systemoutprintln("Got new client:" + sc);
}
/ 如果产生的事件为读取数据(当已连接的客户端向服务器发送数据的时候产生) /
else if ((keyreadyOps() & SelectionKeyOP_READ) == SelectionKeyOP_READ) {
sc = (SocketChannel) keychannel(); // 临时socket对象实例化为产生本事件的socket
ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 定义一个用于存储byte数据的流对象,存储全部信息
echoBufferclear(); // 先将客户端的数据清空
try {
// 循环读取所有客户端数据到byte缓冲区中,当有数据的时候read函数返回数据长度
// NIO会自动的将缓冲区一次容纳不下的自动分段
int readInt = 0; // 为读取到数据的长度
while ((readInt = scread(echoBuffer)) > 0) {
// 如果获得数据长度比缓冲区大小小的话
if (readInt < echoBuffercapacity()) {
byte[] readByte = new byte[readInt]; // 建立一个临时byte数组,将齐长度设为获取的数据的长度
// 循环向此临时数组中添加数据
for (int i = 0; i < readInt; i++) {
readByte[i] = echoBufferget(i);
}
boswrite(readByte); // 将此数据存入byte流中
}
// 否则就是获得数据长度等于缓冲区大小
else {
boswrite(echoBufferarray()); // 将读取到的数据写入到byte流对象中
}
}
// 当循环结束时byte流中已经存储了客户端发送的所有byte数据
log("Recive msg: " + new String(bostoByteArray()));
} catch (Exception e) {
eprintStackTrace(); // 当客户端在读取数据 *** 作执行之前断开连接会产生异常信息
keycancel(); // 将本socket的事件在选择器中删除
break;
}
writeBack(sc, bostoByteArray()); // 向客户端写入收到的数据
}
}
}
} catch (Exception e) {
eprintStackTrace();
}
}
/
绑定服务端口,初始化整个服务
@throws IOException
/
private Selector bindServer() throws IOException {
log("Start binding server socket:" + SOCKET_NUM);
Selector selector = Selectoropen(); // 定义一个事件选择器对象记录套接字通道的事件
ServerSocketChannel ssc = ServerSocketChannelopen(); // 定义一个异步服务器socket对象
sscconfigureBlocking(false);// 将此socket对象设置为异步
ServerSocket ss = sscsocket(); // 定义服务器socket对象-用来指定异步socket的监听端口等信息
InetSocketAddress address = new InetSocketAddress(SOCKET_NUM); // 定义存放监听端口的对象
ssbind(address); // 将服务器与这个端口绑定
sscregister(selector, SelectionKeyOP_ACCEPT); // 将异步的服务器socket对象的接受客户端连接事件注册到selector对象内
log("Binded socket at:" + SOCKET_NUM);
return selector;
}
private boolean writeBack(SocketChannel sc, byte[] b) {
ByteBuffer echoBuffer = ByteBufferallocate(blength); // 建立这个byte对象的ByteBuffer
echoBufferput(b); // 将数据存入
echoBufferflip(); // 将缓冲区复位以便于进行其他读写 *** 作
try {
// 向客户端写入数据,数据为接受到数据
scwrite(echoBuffer);
} catch (IOException e) {
eprintStackTrace();
return false;
}
Systemoutprintln("Msg echo back: " + new String(echoBufferarray()));
return true;
}
private static void log(Object msg) {
Systemoutprintln("SERVER [" + dateFormatterformat(new Date()) + "]: " + msg);
}
}
你好,listen只是设定了等待连接的最大数,因为你有线程接收连接,所以一般不会出现连接不上的情况。
你可以设定一个的int 类型的数据表示当前连接数,当超过这个数就不处理连接了,然后返回给客户端一个数据,让客户端接收到这个数据后知道已经超过最大数了,然后释放连接。
主要是你通过socket api封装要发送的数据,内部会自动封装成数据流进行传输。
1,什么是Socket
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
2,Socket通讯的过程
Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。
对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:
(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写 *** 作;
(4) 关闭Socket(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)
3,创建Socket
创建Socket
java在包javanet中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便。其构造方法如下:
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, boolean stream);
Socket(String host, int prot);
Socket(String host, int prot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, int port, InetAddress localAddr, int localPort)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr)
Socket client = new Socket("127001", 80);
ServerSocket server = new ServerSocket(80);
在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。
以上就是关于TCP及Socket全部的内容,包括:TCP及Socket、请教怎样发送socket请求包,并获得返回数据、C#中如何控制socket最大连接数等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)