Написал сокет-сервер на python (ubuntu), а клиента на c++ (windows). Проблема в том, что на сервере функция recv требует оповещение об закрытиии сокета (shutdown) от клиента, иначе на этом месте скрипт останавливается. Если же я вызову shutdown на стороне клиента, сервер примет сообщение и отправит ответное, но клиент-сокет больше не сможет ни отправлять, ни получать данные (из-за этого shutdown). А мне нужно обмениваться данными в цикле.
Вот примерно так:
клиент:
1.инициализация сокета
2. подключение к серверу
3. отправка данных
4. получение ответа от сервера
5. отправка данных
6. получение ответа от сервера ...
55. закрытие соединения
server.py:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(10)
while 1:
conn, addr = sock.accept()
print('new connection from ' + addr[0] + ":" + str(addr[1]))
data = bytearray()
while 1:
while 1:
chunk = conn.recv(128)
if not chunk:
break
else:
data += chunk
print(str(len(data)) + " bytes received (" + data.decode('ascii', 'strict') + ")")
date = strftime("%Y-%m-%d %H:%M:%S", gmtime())
bytes_len = conn.send(date.encode('ascii'))
print(str(bytes_len) + " bytes sent")
print('closing the connection..')
conn.close()
sock.close()
client.exe:
int send_data(SOCKET sock, const char* data, int datalen)
{
int bytes_len = send(sock, data, datalen, 0);
if (bytes_len < 0) {
return -1;
}
/*if (shutdown(sock, SD_SEND) < 0) {
return -1;
}*/
return bytes_len;
}
int recv_data(SOCKET sock, char* buf)
{
log("0");
int recvlen = 0;
char chunk[128];
memset(chunk, 0, sizeof(chunk));
do {
log("1");
int len = recv(sock, chunk, sizeof(chunk), 0);
log("2");
if (len == -1)
return -1;
if (len == 0)
{
/*if (shutdown(sock, SD_RECEIVE) < 0) {
return -1;
}*/
return recvlen;
}
memcpy(buf + recvlen, chunk, len);
memset(chunk, 0, sizeof(chunk));
recvlen += len;
} while (true);
}
void force()
{
char* ip = "";
int port = 0;
int result;
WSADATA wsaData;
log("socket startup..");
result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
log("wsastartup failed: %d", result);
return;
}
log("creating socket..");
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
log("error creating socket: %d", WSAGetLastError());
WSACleanup();
return;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
log("connecting to %s:%d", ip, port);
result = connect(sock, (sockaddr *)&addr, sizeof(addr));
if (result == SOCKET_ERROR) {
log("Unnable to connect to server: %d", WSAGetLastError());
WSACleanup();
return;
}
for (int i = 0; i < 10; i++)
{
string msg = "hello from windows " + to_string(i);
int bytes_len = send_data(sock, msg.c_str(), msg.length());
if (bytes_len < 0)
{
log("Error sending data: %d", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
log("%d bytes sent..", bytes_len);
char buf[1024];
memset(buf, 0, sizeof(buf));
bytes_len = recv_data(sock, buf);
if (bytes_len < 0)
{
log("Error receiving data: %d", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}
log("%d bytes received (%s)", bytes_len, buf);
}
log("socket closing..");
closesocket(sock);
log("wsa cleanup..");
WSACleanup();
return;
}
Сервер ожидает, что ему придет от клиента 128 байт данных:
chunk = conn.recv(128)
Клиент отправляет явно меньше:
string msg = "hello from windows " + to_string(i);
Вызов conn.recv(128)
- блокирующий, т.е., если в буфере сокета нет данных - он будет ждать.
Спасибо @jfs за замечание
Когда Вы вызываете shutdown(sock, SD_RECEIVE)
отправляется пакет с сегментом FIN (на самом деле их отправляется несколько) - и тогда read возвращает ноль (EOF - с данного сокета вы больше не можете читать данные):
if not chunk:
break
Что в итоге позволяет выйти из цикла.
Виртуальный выделенный сервер (VDS) становится отличным выбором
При компиляции кода в IntelliJ IDEA всё работает отлично, но как только вывожуjar и пытаюсь запустить его, пишет ошибку:
Есть массив, нужно каждый элемент массива прогнать через цикл с добавлением цифрПроблема в том, что код прогоняет только первый элемент массива
Хочу сделать плеер и вот пытаюсь выловить картинку из mp3 файлаПытался установить mp3agic и с помощью него извлечь, но при установки вылезают...
У меня есть интерфейс в котором есть кнопка старт, она запускает Phantomjs, но в момент запуска, интерфейс становиться недоступным, до тех пор...