- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我不知道这是一个普遍的网络问题还是仅仅是一个编程问题,所以我决定把它贴在这里。
尝试制作一个聊天程序,我遇到了以下情况:
- 我启动服务器程序;服务器在端口 22001 上创建套接字;服务器等待连接(接受()挂起);
- 我启动客户端程序;客户端连接无误;客户端发送无误;
- 服务器接收消息;
然后:
- 我在同一端口上启动另一个客户端(客户端程序的另一个实例,而不停止或断开第一个客户端的连接);
- 尽管服务器不再处于“accept() pending”状态,但第二个客户端连接没有错误(?!);
- 第二个客户端发送消息时没有显示任何错误(?!);
- 服务器不接收来自第二个客户端的消息(?!);
实验的最后一步:
- 我在服务器端断开套接字;在这一刻,两个(?!)客户端在发送时都显示错误。
服务器和客户端在同一台机器上运行,并配置为使用端口 22001 和机器的 ip(比如 192.168.123.123)。
我使用带超时的阻塞套接字进行读写,我使用 select() 使 accept() 超时。我使用 SO_REUSEADDR。我承认我并不完全了解 select() 的工作原理。
我知道 tcp/ip 根据以下设置区分连接:服务器 ip、服务器端口、客户端 ip 客户端端口。在我的例子中,客户端端口应该不同,而且看起来它们是不同的。但是 52428 是什么端口(?!),为什么这三个端口都一样(见下面的日志)?远程端口通过 getpeername() 获取,本地端口通过 getsockname() 获取。
我认为可以在同一个端口上的服务器上建立多个连接,但不能在同一个套接字上建立多个连接。我错了吗?
注意服务器断开连接后,客户端1显示错误10053,而客户端2显示错误10054。
那么这一切怎么可能呢?如何在服务器上防止同一套接字上的多个连接但允许同一端口上的多个连接?
程序的输出如下:
Server:
1) Skt 0: SocketListen 116 created - Port 22001 IP 192.168.123.123.
2) Skt 0: Wait for client connection/
3) Skt 0: SocketAccept 120 created.
4) Skt 0: Remote port is 52428 (SocketListen).
5) Skt 0: Remote port is 52428 (SocketAccept).
6) Skt 0: Local port is 22001 (SocketListen).
7) Skt 0: Local port is 22001 (SocketAccept).
8) Skt 0: Client connected.
9) Skt 0: InUse.
10) Skt 0: << Src=Cli1= Dst=Cli2= Body=Text_A_0.
11) Skt 0: << Src=Cli1= Dst=Cli2= Body=Text_B_0.
12) Skt 0: closing...
13) Skt 0: Both sockets (Listen and Accept/Connect) droped.
14) Skt 0: closed.
Client 1:
1) Socket 116 created.
2) Socket connected - Port 22001 IP 192.168.123.123.
3) Remote port is 52428.
4) Local port is 62193
5) Sent to Cli2 CliString: =Text_A_0=.
6) Sent to Cli2 CliString: =Text_B_0=.
7) ERROR !!! Port 22001 cannot be reached. Error =10053.
8) ERROR !!! setsockopt( recv_timeout ) failed.
9) Socket closed.
Client 2:
1) Socket 116 created.
2) Socket connected - Port 22001 IP 192.168.123.123.
3) Remote port is 52428.
4) Local port is 62194
5) Sent to Cli1 CliString: =Text_C_0=.
6) Sent to Cli1 CliString: =Text_D_0=.
7) ERROR !!! Port 22001 cannot be reached. Error =10054.
8) ERROR !!! setsockopt( recv_timeout ) failed.
9) Socket closed.
服务器,部分代码:
class SktSvr
{
uint32 u32SktIdx;
uint16 u16PortNr;
string strIpAddr;
WSADATA wsaData;
struct sockaddr_in sAddr_Svr;
SOCKET SktListen, SktAccept;
int iRes;
thread * pThreadRecv, * pThreadSend;
mutex Mutex_CliId;
static mutex Mutex_MailBoxes;
static map< string, map< string, string > > MailBoxes; // key = destin , key = source, message
public:
char achCliId[ MSG_SRC_STR_LEN + 1 ];
bool bIsPrep;
atomic<bool> bInUse;
SktSvr( uint32 u32SktIdx_p, uint16 u16PortNr_p, char * pchAddr_p = "127.0.0.1" )
{
u16PortNr = u16PortNr_p;
strIpAddr = pchAddr_p;
u32SktIdx = u32SktIdx_p;
bIsPrep = bInUse = false;
pThreadRecv = pThreadSend = NULL;
achCliId[ 0 ] = '\0';
memset( &sAddr_Svr, 0, sizeof( sAddr_Svr ) );
sAddr_Svr.sin_family = AF_INET; // server byte order
wstring wstrIpAddr( strIpAddr.begin(), strIpAddr.end() );
InetPton( AF_INET, wstrIpAddr.c_str(), &sAddr_Svr.sin_addr.s_addr ); //INADDR_ANY; // host addr
sAddr_Svr.sin_port = htons( u16PortNr );
char chOptVal = 1;
if( ( iRes = WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) != NO_ERROR )
{
printf( "\nSkt %d: ERROR !!! WSAStartup failed: %d.", u32SktIdx, iRes );
}
else if( ( SktListen = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) // default protocol
{
printf( "\nSkt %d: ERROR !!! Port %d can not be opened.", u32SktIdx, u16PortNr );
printf( "\nSkt %d: Error =%ld.", u32SktIdx, WSAGetLastError() );
WSACleanup();
}
else if( setsockopt( SktListen, SOL_SOCKET, SO_REUSEADDR, &chOptVal, sizeof( chOptVal ) ) == -1 )
{
printf( "\nSkt %d: ERROR !!! Port %d set options failed.", u32SktIdx, u16PortNr );
printf( "\nSkt %d: Error =%ld.", u32SktIdx, WSAGetLastError() );
WSACleanup();
}
else if( bind( SktListen, ( struct sockaddr * ) &sAddr_Svr, sizeof( sAddr_Svr ) ) == SOCKET_ERROR )
{
printf( "\nSkt %d: ERROR !!! Port %d can not be bound.", u32SktIdx, u16PortNr );
printf( "\nSkt %d: Error =%ld.", u32SktIdx, WSAGetLastError() );
WSACleanup();
}
else if( listen( SktListen, 5 ) == SOCKET_ERROR ) // size for backlog queue = 5
{
printf( "\nSkt %d: ERROR !!! Port %d can not listen.", u32SktIdx, u16PortNr );
printf( "\nSkt %d: Error =%ld.", u32SktIdx, WSAGetLastError() );
WSACleanup();
}
else
{
printf( "\nSkt %d: SocketListen %d created - Port %d IP %s.",
u32SktIdx, SktListen, u16PortNr, strIpAddr.c_str() );
bIsPrep = true;
}
}
bool SktConn()
{
int iRes;
struct timeval tmvl;
fd_set rfds;
FD_ZERO( &rfds );
FD_SET( SktListen, &rfds );
tmvl.tv_sec = TIMEOUT_SKT_CONN_S;
tmvl.tv_usec = 0;
if( 0 ) {}
else if( 1 && ( iRes = select( SktListen + 1, &rfds, (fd_set*)0, (fd_set*)0, &tmvl ) ) <= 0 )
{
// connect timeout
//printf( "\nSkt %d: Socket Connect timeout.", u32SktIdx );
bInUse = false;
}
else if( ! FD_ISSET( SktListen, &rfds ) )
{
printf( "\nSkt %d: Selected another.", u32SktIdx );
}
else if( ( SktAccept = accept( SktListen, NULL, NULL ) ) == INVALID_SOCKET )
{ printf( "\nSkt %d: ERROR !!! Port %d did not connect.", u32SktIdx, u16PortNr );
printf( "\nSkt %d: Error =%ld.", u32SktIdx, WSAGetLastError() );
bInUse = false;
}
else
{
printf( "\nSkt %d: SocketAccept %d created.", u32SktIdx, SktAccept );
struct sockaddr_in sAddr;
socklen_t len;
getpeername( SktListen, ( struct sockaddr* )&sAddr, &len );
printf( "\nSkt %d: Remote port is %d (SocketListen).", u32SktIdx, ntohs( sAddr.sin_port ) );
getpeername( SktAccept, ( struct sockaddr* )&sAddr, &len );
printf( "\nSkt %d: Remote port is %d (SocketAccept).", u32SktIdx, ntohs( sAddr.sin_port ) );
int iAddrLen = sizeof( sAddr );
if( getsockname( SktListen, ( struct sockaddr * )&sAddr, &iAddrLen ) == 0 &&
sAddr.sin_family == AF_INET && iAddrLen == sizeof( sAddr ) )
printf( "\nSkt %d: Local port is %d (SocketListen).", u32SktIdx, ntohs( sAddr.sin_port ) );
if( getsockname( SktAccept, ( struct sockaddr * )&sAddr, &iAddrLen ) == 0 &&
sAddr.sin_family == AF_INET && iAddrLen == sizeof( sAddr ) )
printf( "\nSkt %d: Local port is %d (SocketAccept).", u32SktIdx, ntohs( sAddr.sin_port ) );
bInUse = true;
}
return bInUse;
}
最佳答案
单个监听套接字用于在单个端口上接受任意数量的连接。 accept()
为每个连接创建并返回一个新的套接字,这就是“每个连接一个套接字”的由来。你从来没有听到第二个客户端发送的消息的原因是你只recv()
来自连接到第一个客户端的套接字。
如果在客户端连接时监听套接字不在 accept()
调用内,则传入连接会排队。这是标准套接字行为,您不仅会在 Windows 上看到它,还会在 BSD、Linux 等上看到它。
接受队列的大小是套接字选项。
如果您不想要排队行为,则必须在接受第一个连接后立即关闭监听套接字。但几乎可以肯定,您想要的是使用 select()
(或 WSAEventSelect
、poll
等)来监视客户端套接字和监听套接字,当监听套接字显示事件时,再次调用 accept()
并立即激活多个连接到客户端的套接字。
关于c++ - window ,C++ : two connections on one server socket?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41618664/
基于 socket.io 的官方网站 http://socket.io/#how-to-use , 我找不到任何术语。socket.emit 、 socket.on 和 socket.send 之间有
我正在使用 lua-socket 3.0rc1.3(Ubuntu Trusty 附带)和 lua 5.1。我正在尝试监听 unix 域套接字,我能找到的唯一示例代码是 this -- send std
这两者有什么区别? 我注意到如果我在一个工作程序中从 socket.emit 更改为 socket.send ,服务器无法接收到消息,虽然我不明白为什么。 我还注意到,在我的程序中,如果我从 sock
使用套接字在两台服务器之间发送数据是个好主意,还是应该使用 MQ 之类的东西来移动数据。 我的问题:套接字是否可靠,如果我只需要一次/有保证的数据传输? 还有其他解决方案吗? 谢谢。 最佳答案 套接字
引自 this socket tutorial : Sockets come in two primary flavors. An active socket is connected to a
我已经安装了在端口81上运行的流服务器“Lighttpd”(light-tpd)。 我有一个C程序,它使用套接字api创建的服务器套接字在端口80上监听http请求。 我希望从客户端收到端口80上的请
这是我正在尝试做的事情: 当有新消息可用时,服务器会将消息发送给已连接的客户端。另一方面,客户端在连接时尝试使用send()向服务器发送消息,然后使用recv()接收消息,此后,客户端调用close(
如何将消息发送到动态 session 室,以及当服务器收到该消息时,如何将该消息发送到其他成员所在的同一个 session 室? table_id是房间,它将动态设置。 客户: var table_i
这是我尝试但不起作用的方法。我可以将传入的消息从WebSocket连接转发到NetSocket,但是只有NetSocket收到的第一个消息才到达WebSocket后面的客户端。 const WebSo
我正在实现使用boost将xml发送到客户端的服务器。我面临的问题是缓冲区不会立即发送并累积到一个点,然后发送整个内容。这在我的客户端造成了一个问题,当它解析xml时,它可能具有不完整的xml标记(不
尝试使用Nginx代理Gunicorn套接字。 /etc/systemd/system/gunicorn.service文件 [Unit] Description=gunicorn daemon Af
我正在使用Lua套接字和TCP制作像聊天客户端和服务器这样的IRC。我要弄清楚的主要事情是如何使客户端和服务器监听消息并同时发送它们。由于在服务器上执行socket:accept()时,它将暂停程序,
我看了一下ZMQ PUSH/PULL套接字,尽管我非常喜欢简单性(特别是与我现在正在通过UDP套接字在系统中实现的自定义碎片/ack相比),但我还是希望有自定义负载平衡功能,而不是幼稚的回合-robi
我正在编写一个应用程序,其中有多个 socket.io 自定义事件,并且所有工作正常,除了这个: socket.on("incomingImg", function(data) {
在我的应用程序中,我向服务器发送了两条小消息(类似 memcached 的服务)。在类似 Python 的伪代码中,这看起来像: sock.send("add some-key 0") ignored
很抱歉再次发布此问题,但大多数相关帖子都没有回答我的问题。我在使用 socket.io 的多个连接时遇到问题我没有使用“socket.socket.connect”方法,但我从第一次连接中得到了反馈。
我尝试使用 socket.io 客户端连接到非 socket.io websocket 服务器。但我做不到。我正在尝试像这样连接到套接字服务器: var socket = io.connect('ws
我遇到了一个奇怪的问题。在我非常基本的服务器中,我有: server.listen(8001); io.listen(server); var sockets = io.sockets; 不幸的是,套
我正在使用带套接字 io 的sailsjs。帆的版本是 0.10.5。我有以下套接字客户端进行测试: var socketIOClient = require('socket.io-client');
这个问题在这里已经有了答案: What is the fundamental difference between WebSockets and pure TCP? (4 个答案) 关闭 4 年前。
我是一名优秀的程序员,十分优秀!