Datagram套接字服务器未从客户端接收消息
Datagram socket server not receiving messages from client
我有使用UNIX Datagram套接字连接与C 客户端通信的Python服务器。以下代码设置插座,然后发送并从客户端接收一条消息。但是,该脚本在Python 2.7中起作用,但是,在Python 3中测试它时,请调用Recv()times Out等待客户端的消息。但是,客户端确实在没有问题的情况下从服务器接收消息。我已经使用3.5.2和3.7.1在两台单独的机器中对此进行了测试。
update :我添加了一个IOLOOP(Asyncio事件循环包装器),以创建一个回调系统,以适用于套接字上的消息准备就绪。当服务器使用Python 2.7运行时,来自客户端的消息出现,但是使用Python 3.7.1从未收到任何收到。
C 客户端来源:
// Socket Client
#include <stdio.h>
#include <stdlib.h>
#include <cerrno>
#include <vector>
#include <string>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstdarg>
using namespace std;
int sock;
bool await_connection = true;
vector<sockaddr_un> dest_addrs;
int max_msg_size = 2048;
string msg_buf;
string sock_name = "test.sock";
void receive_control_message()
{
char buf[4096]; // Should be enough for client->server messages
sockaddr_un srcaddr;
socklen_t srcaddr_len;
srcaddr_len = sizeof(srcaddr);
int len = recvfrom(sock, buf, sizeof(buf),
0, (sockaddr *) &srcaddr, &srcaddr_len);
if (len == -1)
{
fprintf(stderr,"Socket read error: %sn", strerror(errno));
exit(-1);
}
printf("sockaddr_un sun_path: '%s'n", srcaddr.sun_path);
dest_addrs.push_back(srcaddr);
string data(buf, len);
fprintf(stderr, "websocket: Received control message in %d byte.n", (int) data.size());
printf("%sn", data.c_str());
}
void finish_message()
{
if (msg_buf.size() == 0)
return;
const int initial_buf_size = msg_buf.size();
fprintf(stderr, "websocket: About to send %d bytes.n", initial_buf_size);
if (sock_name.empty())
{
msg_buf.clear();
return;
}
msg_buf.append("n");
const char* fragment_start = msg_buf.data();
const char* data_end = msg_buf.data() + msg_buf.size();
int fragments = 0;
while (fragment_start < data_end)
{
int fragment_size = data_end - fragment_start;
if (fragment_size > max_msg_size)
fragment_size = max_msg_size;
fragments++;
for (unsigned int i = 0; i < dest_addrs.size(); ++i)
{
int retries = 30;
ssize_t sent = 0;
while (sent < fragment_size)
{
ssize_t retval = sendto(sock, fragment_start + sent,
fragment_size - sent, 0, (sockaddr*) &dest_addrs[i],
sizeof(sockaddr_un));
fprintf(stderr, " trying to send fragment to client %d...n", i);
if (retval <= 0)
{
const char *errmsg = retval == 0 ? "No bytes sent"
: strerror(errno);
if (--retries <= 0)
{
fprintf(stderr,"Socket write error: %sn", errmsg );
exit(-1);
}
if (retval == 0 || errno == ENOBUFS || errno == EWOULDBLOCK
|| errno == EINTR || errno == EAGAIN)
{
// Wait for half a second at first (up to five), then
// try again.
const int sleep_time = retries > 25 ? 2 * 1000
: retries > 10 ? 500 * 1000
: 5000 * 1000;
fprintf(stderr, "failed (%s), sleeping for %dms.n",
errmsg, sleep_time / 1000);
usleep(sleep_time);
}
else if (errno == ECONNREFUSED || errno == ENOENT)
{
// the other side is dead
fprintf(stderr, "failed (%s), breaking.n", errmsg);
dest_addrs.erase(dest_addrs.begin() + i);
i--;
break;
}
else
{
fprintf(stderr,"Socket write error: %sn", errmsg);
}
}
else
{
fprintf(stderr, "fragment size %d sent.n", fragment_size);
sent += retval;
}
}
}
fragment_start += fragment_size;
}
msg_buf.clear();
fprintf(stderr, "websocket: Sent %d bytes in %d fragments.n", initial_buf_size, fragments);
}
void send_message(const char *format, ...)
{
char buf[2048];
int len;
va_list argp;
va_start(argp, format);
if ((len = vsnprintf(buf, sizeof(buf), format, argp)) >= (int)sizeof(buf)
|| len == -1)
{
if (len == -1)
{
fprintf(stderr, "Webtiles message format error! (%s)", format);
exit(-1);
}
else
{
fprintf(stderr, "Webtiles message too long! (%d)", len);
exit(-1);
}
}
va_end(argp);
msg_buf.append(buf);
finish_message();
}
int main()
{
if (sock_name.empty()) return 0;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (sock < 0)
{
printf("Can't open the webtiles socket!n");
exit(-1);
}
sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sock_name.c_str());
if (::bind(sock, (sockaddr*) &addr, sizeof(sockaddr_un)))
{
printf("Can't bind the webtiles socket!n");
exit(-1);
}
int bufsize = 64 * 1024;
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)))
{
printf("Can't set buffer size!n");
exit(-1);
}
// Need small maximum message size to avoid crashes in OS X
max_msg_size = 2048;
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
{
printf("Can't set send timeout!n");
exit(-1);
}
printf("Awaiting connection...n");
if (await_connection)
{
while (dest_addrs.size() == 0) receive_control_message();
}
send_message("{"foo":"grapes","boo":"chicken"}");
send_message("*{"msg":"flush_messages"}");
return 0;
}
服务器脚本
# Socket Server
import socket
import json
from datetime import datetime, timedelta
import warnings
import os,sys
from tornado.ioloop import IOLoop
crawl_socket = None
crawl_socketpath = 'test.sock'
socketpath = 'crawl_socket'
msg_buffer = None
ioloop = IOLoop.instance()
def json_encode(value):
return json.dumps(value).replace("</", "<\/")
def close():
global crawl_socket
if crawl_socket:
print ("Closing socket...")
crawl_socket.close()
os.unlink(socketpath)
crawl_socket = None
def message_callback(data):
if len(data) > 0 and not data.startswith("*"):
print(json.loads(data))
elif data.startswith("*"):
print(json.loads(data[1:]))
def handle_data(data):
global msg_buffer
if msg_buffer is not None:
data = msg_buffer + data
if data[-1] != "n":
# All messages from crawl end with n.
# If this one doesn't, it's fragmented.
msg_buffer = data
else:
msg_buffer = None
message_callback(data)
def handle_read(fd, events):
if events & ioloop.READ:
data = crawl_socket.recv(128 * 1024, socket.MSG_DONTWAIT)
handle_data(data)
if events & ioloop.ERROR:
pass
try:
os.unlink(socketpath)
except OSError:
if os.path.exists(socketpath):
raise
if os.path.exists(crawl_socketpath) and not os.path.exists(socketpath):
crawl_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
crawl_socket.settimeout(10)
crawl_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if (crawl_socket.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) < 2048):
crawl_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2048)
if (crawl_socket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) < 212992):
crawl_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 212992)
msg = json_encode({ "msg": "attach", "primary": True })
with warnings.catch_warnings():
warnings.simplefilter("ignore")
crawl_socket.bind(socketpath)
try:
crawl_socket.sendto(msg.encode('utf-8'), crawl_socketpath)
except socket.timeout:
print("ERROR: in send_message() - Game socket send timeout")
close()
sys.exit(-1)
ioloop.add_handler(crawl_socket.fileno(),
handle_read,
ioloop.ERROR | ioloop.READ)
ioloop.start()
else:
print('%s does not exist' % crawl_socketpath)
我设法自己解决了这个问题,因此,这是任何在将来洞悉类似问题的人的答案。
socket.recv()python 2中的2返回一个代表收到数据的str对象。
在python 3中,这已经更改,socket.recv()返回一个字节对象。
因此,需要添加以下以下内容:
if isinstance(data,bytes):
data = data.decode("utf-8")
相关文章:
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 我正在编写一个简单的客户端套接字应用程序,但在连接后服务器收到一个空缓冲区
- 防止客户端套接字程序崩溃CPP Google Protobuf
- 为什么在此 UDP 客户端/服务器示例中没有必要绑定客户端套接字?
- 客户端套接字是可绑定的,但不可连接,因为已在使用中
- 是否可以寻址另一个网络中的服务器/客户端套接字?(C++)
- 关闭客户端套接字时如何防止服务器关闭?C++
- 多连接客户端套接字应用程序C++
- C 选择仅检查最后一个客户端套接字
- 在两个客户端套接字之间发送数据
- Qt 5: 如何制作"pure c++"客户端套接字?
- Winsock 客户端套接字无效
- C++面向对象的客户端套接字应用程序设计
- 如何强制 udp 服务器接收的 udp 客户端套接字绑定到特定客户端端口
- 客户端套接字连接() 在服务器 accept() 超时后成功
- 如果客户端的互联网断开连接,客户端套接字不会关闭。如何在服务器中检测此事件?
- 客户端套接字在c++中发送到服务器
- 服务器和客户端套接字连接问题重新。send(), accept() 和多线程
- 使用c++ TCP客户端套接字在特定的网络接口Linux/Unix