如何解决socket阻塞

作者&投稿:包亚 (若有异议请与网页底部的电邮联系)
如何把该socket设置为阻塞模式~

提供借鉴:阻塞SOCKET的非阻塞连接
//用非阻塞方式连接,这样的话,一旦连接不上,界面不会出现一段较长时间不响应。
int tcp_connect(char *ip, int port, struct timeval *timeout)
{
struct linger opt;
struct sockaddr_in sin;
struct linger lg;
int sock;
int nodelay;
unsigned long ul;
fd_set fdConnect;

memset(&lg, 0, sizeof(struct linger));

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
TRACE("socket errno:%d
", WSAGetLastError());
return -1;
}

ul = 1;
if (ioctlsocket(sock, FIONBIO, &ul) == SOCKET_ERROR)
{
TRACE("ioctlsocket errno:%d
", WSAGetLastError());
goto err_exit;
}

memset(&sin, 0, sizeof(sin));

sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = inet_addr(ip);
sin.sin_port = htons(port);


if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) == 0)
{
goto ONCE_SUC;
}

FD_ZERO(&fdConnect);
FD_SET((unsigned int)sock, &fdConnect);

if (select(0, 0, &fdConnect, 0, timeout) <= 0)
{
TRACE("select errno:%d
", WSAGetLastError());
goto err_exit;
}

ONCE_SUC:
ul = 0;
if (ioctlsocket(sock, FIONBIO, &ul) == SOCKET_ERROR)
{
TRACE("ioctlsocket errno:%d
", WSAGetLastError());
goto err_exit;
}

/*消除滞留*/
memset(&opt, 0, sizeof(struct linger));
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char*)&opt, sizeof(opt)) == SOCKET_ERROR)
{
TRACE("SO_LINGER errno:%d
", WSAGetLastError());
}

/*禁用合并*/
nodelay = 1;
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*) &nodelay, sizeof(int)) == SOCKET_ERROR)
{
TRACE("TCP_NODELAY errno:%d
", WSAGetLastError());
}

return sock;
err_exit:
closesocket(sock);
return -1;
}

Windows套接字在阻塞和非阻塞两种模式下执行I/O操作。在阻塞模式下,在I/O操作完成前,执行的操作函数一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式下,套接字函数会立即返回,而不管I/O是否完成,该函数所在的线程会继续运行。

在阻塞模式的套接字上,调用任何一个Windows Sockets API都会耗费不确定的等待时间。图所示,在调用recv()函数时,发生在内核中等待数据和复制数据的过程。

当调用recv()函数时,系统首先查是否有准备好的数据。如果数据没有准备好,那么系统就处于等待状态。当数据准备好后,将数据从系统缓冲区复制到用户空间,然后该函数返回。在套接应用程序中,当调用recv()函数时,未必用户空间就已经存在数据,那么此时recv()函数就会处于等待状态。

Socket通讯产生阻塞的解决方案
Socket通讯正常想实现的流程:
是客户端给服务端发送发送报文,当服务端接收到报文后,给客户端一个反馈信息。
目前代码实现情况是:
客户端和服务端在read时都被阻塞了,经过反复的查阅相关资料和测试,发现了问题的根本。
导致read阻塞的原因是:
当客户端给服务端发送完数据的时候服务端在读取数据,但是服务端没有办法判断什么时候会自动中断,所以服务端会在这个地方阻塞。
阻塞之后服务端就没有办法往客户端发送数据,这个时候客户端的接收数据也会等服务端的数据,会在这里阻塞。这个时候服务端和客户端都不会关闭,会一直持续阻塞。
客户端传递数据的时候,服务端不知道什么时候终止,用read!=-1是没有办法判断出来的,因为客户端流没有终止,流一直存在,所以服务端以为数据没有传输完毕。
有两个解决方案,方案如下:
1.在客户端传输结束之后,你可以把流进行关闭,使用socket.shutdownOutput()和socket.shutdownInput()这两个方法,将流关闭掉,对面就可以接收到结束的信号。
2.双方约定好,定义一个结束符,客户端每次给服务端发送报文时,在发送结束加上结束符;当服务端这面接收到报文读取时,读到结束符的话,就证明是结束了,就不在循环了。
方案1服务端代码:
[java] view plain copy
package com.pactera.ok;

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

/**
* @Title:TestZLFServer
* @Description:
* @company:XXXXXX
* @author:XXXXXX-zhanglf
* @date:2017-5-16
* @version:1.0.0
*/
public class TestZLFServer {
public static void main(String[] args) {
try {
ServerSocket ss=new ServerSocket(10086);
Socket s=ss.accept();
InputStream is=s.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os);
//读取用户输入信息
String info=null;
while(((info=br.readLine()) !=null)){
System.out.println("我是服务器,用户信息为:"+info);
<span style="color:#ff0000;">s.shutdownInput();</span>
}

//给客户端一个响应
String result="客户端,我收到你发过的信息了,通知你一下";
pw.write(result);
pw.flush();

pw.close();
os.close();
br.close();
is.close();
s.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
方案1客户端代码:
[java] view plain copy
package com.pactera.ok;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
* @Title:TestZLFClient
* @Description:
* @company:XXXXXX
* @author:XXXXXX-zhanglf
* @date:2017-5-16
* @version:1.0.0
*/
public class TestZLFClient {
public static void main(String[] args) {
try {
Socket s =new Socket(InetAddress.getLocalHost(),10086);
OutputStream os=s.getOutputStream();
PrintWriter pw=new PrintWriter(os);
InputStream is=s.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
//给服务端发送的短信内容
String info="ssssssssssss";
pw.write(info);
pw.flush();
<span style="color:#ff0000;">s.shutdownOutput(); //不加这句代码,客户端输出不了给果: </span>
//接收服务器的相应
String result=null;
while(!((result=br.readLine())==null)){
System.out.println("接收服务器的信息:"+result);
}
//关闭资源
br.close();
is.close();
pw.close();
os.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
方案2服务端代码:
[java] view plain copy
package com.pactera.ok3;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
* @Title:Server3
* @Description:
* @company:XXXXX
* @author:XXXXX-zhanglf
* @date:2017-5-16
* @version:1.0.0
*/
public class Server3 {

public static void main(String[] args) {
try {
// 创建一个服务端ServerSocket,监听指定端口的请求
ServerSocket ss = new ServerSocket(10086);
System.out.println("=============Server 等待客户端接入===============");
// 监听客户端请求
Socket socket = ss.accept();
// 与客户端建立连接之后,读取客户端发过来的信息
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
// 定义一个字符串构建器,用于存储客户端发过来的数据
StringBuilder sb = new StringBuilder();
int index;
while ( (len=is.read(buffer)) != -1 ) {
String temp = "";
String tmp = new String(buffer, 0, 2);
/**01-单独给信贷系统增加的处理逻辑**/
if("xd".equals(tmp)){
temp = new String(buffer, 0, len);
//System.out.println("temp ====== : "+temp);
// 读到结束符,则跳出循环
if ( (index=temp.indexOf("eof")) != -1 ) {
// 截取指定长度
sb.append(temp.substring(2, index));
break;
}
}else{
/**02-核心原有处理逻辑**/
temp = new String(buffer, 0, len);
}
// 如果没有读到结束符,则继续读取,并加入字符串构建器
sb.append(temp);
}
System.out.println("Server 来自客户端的信息 : " + sb.toString());
// 读完之后,往客户端发送响应数据
OutputStream out = socket.getOutputStream();
out.write("Hello Client!".getBytes());
out.write("eof".getBytes());// 写一个结束符
out.flush();
out.close();
is.close();
socket.close();
ss.close();
}catch (Exception e) {
e.printStackTrace();
}
}

}
方案2客户端代码:
[java] view plain copy
package com.pactera.ok3;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
* @Title:Client3
* @Description:
* @company:XXXXX
* @author:XXXXX-zhanglf
* @date:2017-5-16
* @version:1.0.0
*/
public class Client3 {

public static void main(String[] args) {
try{
// 与服务端建立连接(服务端主机号,服务端监听的端口号)
Socket socket = new Socket(InetAddress.getLocalHost(),10086);
// 与服务端建立连接之后,就可以往服务端写数据
OutputStream out = socket.getOutputStream();
// 往服务端中写数据
out.write("xd|0|001101|150XXXXXXXX|您好,你卡号取款200元。|".getBytes());
out.write("eof".getBytes());// 写一个结束符,表示写入完毕
out.flush();
// 写完之后,获取服务端的响应数据
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
// 定义一个StringBuilder存储客户端发过来的数据
StringBuilder sb = new StringBuilder();
int index;
while ( (len=is.read(buffer)) != -1 ) {
String temp = new String(buffer, 0, len);
// 读到结束符,则跳出循环
if ( (index=temp.indexOf("eof")) != -1) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("Client 来自服务端的信息 : " + sb.toString());
out.close();
is.close();
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
}

}


socket未连接怎么办
socket未连接解决方法:1、检查网络:socket未连接可能是因为网络故障导致的,需要检查并更换网络;2、重新设置服务器地址:socket未连接可能是在输入服务器地址的时候,没有正确注入,导致socket无法识别到,需要设置服务器地址,并保证服务器的准确性;3、重新编写代码:socket未连接可能是在设置代码的时候,...

手机应用Socket未连接怎么解决呢?
1. 网络问题:请确保你的手机已连接到可用的网络,并且网络连接正常。你可以尝试切换到其他网络或重新连接网络。2. 服务器问题:如果应用程序尝试连接的服务器出现问题,可能会导致 Socket 连接失败。你可以尝试检查服务器状态或联系应用程序的开发者以获取帮助。3. 应用程序问题:应用程序本身可能存在问题,...

如何解决socket阻塞
1.在客户端传输结束之后,你可以把流进行关闭,使用socket.shutdownOutput()和socket.shutdownInput()这两个方法,将流关闭掉,对面就可以接收到结束的信号。2.双方约定好,定义一个结束符,客户端每次给服务端发送报文时,在发送结束加上结束符;当服务端这面接收到报文读取时,读到结束符的话,就证...

360系统重装后socket连接失败,纯电脑小白,怎么能解决问题?
方案一 打开命令提示符,输入netsh winsock reset,并回车,然后重启计算机即可;方案2 直接打开360安全卫士,点击右下角的“更多”;点击工具中的“断网急救箱”,打开后点击“全面诊断”按钮;诊断完后,点击“立即修复”;

socket+error+10053怎么解决?
检查网络连接是否稳定:Socket Error 10053 可能是由于网络连接不稳定导致的。您可以尝试重新启动计算机或路由器,或者联系网络管理员进行帮助和支持。检查防火墙设置:防火墙可能会阻止网络连接或中断现有的连接,导致 Socket Error 10053。您可以尝试暂时关闭防火墙或检查防火墙设置,以确保它们不会阻止您的连接。

w10socket环境失败,无法联网怎么解决
三种可能:1.网速问题 2.病毒问题 3.电脑配置速度问题 以下几种解决方法:1.安全模式下查杀一下是否有病毒,2.或者重新安装浏览器看是否出现类似情况 3.更换其他浏览器试试 4.用别的电脑链接你的网线试验一下,如果出现类似情况,说明是你的网速问题 5.最后一招。。修复系统 ...

w10socket环境失败,无法联网怎么解决
三种可能:1. 网速问题 2. 病毒问题 3. 电脑配置速度问题 以下几种解决方法:1. 安全模式下查杀一下是否有病毒,2. 或者重新安装浏览器看是否出现类似情况 3. 更换其他浏览器试试 4. 用别的电脑链接你的网线试验一下,如果出现类似情况,说明是你的网速问题 5. 最后一招。。修复系统 ...

socket连接超时怎么解决啊
调大timeout参数值。网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。当socket连接超时调大timeout参数值,可以解决连接超时的问题。timeout就是连接等待的时间参数,把原来的等待时间调大即可。

socket write error怎么解决
socket write error,是设置错误造成的,解决方法如下:1、首先打开电脑,来到桌面右下角通知栏,鼠标移至程序图标。2、然后右键选择“重新载入”,过会儿再试是否能成功连接。3、或者退出、关闭程序,过会儿再试是否还报错。4、还可以在电脑上打开安全卫士的点击加速球按钮,再点其上的“上网管理”。5...

socket丢包怎么解决
那么客户端收到的数据就会比理论应该收到的少,就会造成丢数据,丢包的现象。这种现象,其实本质上来说不是丢包,也不是丢数据,只是因为程序处理有错误,导致有些数据没有成功地被socket发送出去。常用的解决方法如下:拆包、加包头、发送,组合包,如果客户端、服务端掉线,常采用心跳测试。

红桥区13824597502: 如何解决socket阻塞 -
连瞿凯时: Socket通讯产生阻塞的解决方案 Socket通讯正常想实现的流程: 是客户端给服务端发送发送报文,当服务端接收到报文后,给客户端一个反馈信息. 目前代码实现情况是: 客户端和服务端在read时都被阻塞了,经过反复的查阅相关资料和测试...

红桥区13824597502: 如何解决socket通信中的阻塞 -
连瞿凯时: myisam_recover=64K#允许的GROUP_CONCAT()函数结果的最大长度transaction_isolation=REPEATABLE-READinnodb_file_per_table

红桥区13824597502: Socket关闭后,接收函数仍然阻塞,怎么让它返回 -
连瞿凯时: 在别处调用socket.Close后接收函数仍然阻塞,并不返回.服务端发来数据后,甚至仍然能够读出正确的数据,而之后才因为错误,说socket已经是null.

红桥区13824597502: 如何唤醒socket被阻塞的函数
连瞿凯时: 最近项目遇到一个问题,程序退出的时候资源没有正常释放.经过调试发现,原来是网络线程一直阻塞,导致一些必要的资源没有被释放,写了几个简单的测试程序调试了一下才明白,原来在Linux下直接close socket的文件描述符,并不会使程...

红桥区13824597502: 如何 释放 socket 缓冲区 -
连瞿凯时: 如果是在客户端,当你close一个socket的时候,就连带的将此socket的接收和发送buffer都撤销了,自然也就清空了.如果在服务器端,一般你不需要担心客户端会读入遗留数据,因为当在socket上发送报文时,是按照IP:PORT的形式辨别每一个连接的.当你的客户端再次连接,IP虽然相同,但port已经不同了.

红桥区13824597502: 使用socket.recv时出现阻塞,怎么处理 -
连瞿凯时: recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结. 首先阻塞接收的recv有时候会返回0,这仅在对端已经关...

红桥区13824597502: JAVA中Socket通信阻塞问题
连瞿凯时: "阻塞"使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的. 可以用下面的语句 ServerSocket.accept() : public Socket accept() throws IOException {...} 这样产生的"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例

红桥区13824597502: 外网socket不通怎么办 -
连瞿凯时: 需要设置路由的端口映射,否则外网是访问不到你内网IP的

红桥区13824597502: java 中Socket怎么从阻塞模式中出来 -
连瞿凯时: java nio, serversocketchannel是非阻塞的, 参考mina开源代码 打开阻塞就是往Selector发一点基本数据.

红桥区13824597502: Socket阻塞长连接 -
连瞿凯时: 长连接就是客户端和服务器端建立了socket 连接以后,该连接在使用完毕以后,并不马上关闭掉,而是保持此连接,如果下一次需要和服务器进行通信,就立即启用该连接 进行数据的通信.当然,保持长连接,必须检查该连接的状态(是否断开).

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网