Udp image transefing is too slow - python

I'm trying to send an image from C# to Python side via UDP. I split the image by 1024 bytes and send those chunks. On the Python side - I accept and merge them. The problem is speed. The image, which weighs about 200 KB, takes about 7 seconds to send. I read some questions about similar problems with UDP, but nothing helps. What can I do to speed up this connection? Thanks!
The sample image:
Python side:
import time
import threading
import socket
import traceback
import warnings
class ListenPort:
def __init__(self, port: int, is_camera: bool = False):
self.__port = port
self.__is_camera = is_camera
self.thread = None
self.__stop_thread = False
self.out_string = ""
self.out_bytes = b""
self.ip_end_point = ('127.0.0.1', self.__port)
self.sct = None
def start_listening(self):
self.thread = threading.Thread(target=self.listening, args=())
self.thread.start()
def listening(self):
self.sct = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("connected: " + str(self.__port))
while not self.__stop_thread:
try:
if self.__is_camera:
self.sct.sendto("Wait for size".encode('utf-16-le'), self.ip_end_point)
image_size, _ = self.sct.recvfrom(4)
print(len(image_size))
if len(image_size) < 4:
continue
buffer_size = (image_size[3] & 0xff) << 24 | (image_size[2] & 0xff) << 16 | \
(image_size[1] & 0xff) << 8 | (image_size[0] & 0xff)
self.sct.sendto("Wait for image".encode('utf-16-le'), self.ip_end_point)
local_bytes = b""
check_iters = 0
for i in range(0, buffer_size // 1024):
local_bytes += self.sct.recvfrom(1024)[0]
self.sct.sendto("Got data".encode('utf-16-le'), self.ip_end_point)
check_iters += 1
print(check_iters)
print(check_iters)
if buffer_size % 1024 > 0:
local_bytes += self.sct.recvfrom(buffer_size % 1024)[0]
self.out_bytes = local_bytes
else:
self.sct.sendto("Wait for data".encode('utf-16-le'), self.ip_end_point)
self.out_bytes, _ = self.sct.recvfrom(1024)
self.out_string = self.out_bytes.decode('utf-16-le')
except OSError:
break
except (Exception, EOFError):
traceback.print_exc()
print("disconnected: " + str(self.__port))
def reset_out(self):
self.out_string = ""
self.out_bytes = b""
def stop_listening(self):
self.__stop_thread = True
self.reset_out()
if self.sct is not None:
self.sct.shutdown(socket.SHUT_RDWR)
if self.thread is not None:
st_time = time.time()
while self.thread.is_alive():
if time.time() - st_time > 2:
warnings.warn("Something went wrong. Rude disconnection on port " + str(self.__port))
self.sct.close()
st_time = time.time()
listen = ListenPort(63213, True)
listen.start_listening()
st_time = time.time()
while True:
if len(listen.out_bytes) == 218669:
print("got image")
break
print(time.time() - st_time)
listen.stop_listening()
# the out of print(time.time() - st_time) is 7.35678505897522
C# side:
public struct Received
{
public IPEndPoint Sender;
public string Message;
}
public abstract class UdpBase
{
protected UdpClient Client;
protected UdpBase()
{
Client = new UdpClient();
}
public async Task<Received> Receive()
{
var result = await Client.ReceiveAsync();
return new Received()
{
Message = Encoding.Unicode.GetString(result.Buffer, 0, result.Buffer.Length),
Sender = result.RemoteEndPoint
};
}
}
public class TalkPortUdp : UdpBase
{
private bool stopTask = false;
private IPEndPoint _talkOn;
private string outString = "";
private byte[] outBytes = new byte[10];
public IPEndPoint sender;
public Task task;
public TalkPortUdp(IPEndPoint endpoint)
{
_talkOn = endpoint;
}
public void SetString(string data)
{
outString = data;
}
public void SetBytes(byte[] data)
{
outBytes = data;
}
public void Send(string message, IPEndPoint endpoint)
{
var datagram = Encoding.Unicode.GetBytes(message);
Client.Send(datagram, datagram.Length, endpoint);
}
public void SendBytes(byte[] message, IPEndPoint endpoint)
{
Client.Send(message, message.Length, endpoint);
}
public void StartTalking()
{
Client = new UdpClient(_talkOn);
stopTask = false;
task = Task.Run(() => {
while (!stopTask)
{
try
{
if (this.Client.Available > 0)
{
var received = this.Receive().GetAwaiter().GetResult();
string clientTask = received.Message;
sender = received.Sender;
if (clientTask.Contains("Wait for size"))
{
byte[] intBytes = BitConverter.GetBytes(outBytes.Length);
this.SendBytes(intBytes, received.Sender);
}
else if (clientTask.Contains("Wait for image"))
{
for (int i = 0; i < outBytes.Length - 1024; i += 1024)
{
byte[] second = new byte[1024];
Buffer.BlockCopy(outBytes, i, second, 0, 1024);
Console.WriteLine(i);
this.SendBytes(second, received.Sender);
received = this.Receive().GetAwaiter().GetResult();
}
int lastt = outBytes.Length % 1024;
if (lastt > 0)
{
byte[] lasttBytes = new byte[lastt];
Buffer.BlockCopy(outBytes, outBytes.Length - lastt, lasttBytes, 0, lastt);
this.SendBytes(lasttBytes, received.Sender);
}
}
else if (clientTask.Contains("Wait for data"))
{
this.Send(outString, received.Sender);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Console.WriteLine("Stopped");
});
}
public bool IsAlive()
{
if (task != null)
return task.Status.Equals(TaskStatus.Running);
return false;
}
public void StopTalking()
{
stopTask = true;
Client.Dispose();
Client.Close();
}
}
internal class Program
{
static void Main(string[] args)
{
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Any, 63213);
TalkPortUdp talk = new TalkPortUdp(ipPoint);
talk.StartTalking();
while (true)
{
// Load file meta data with FileInfo
FileInfo fileInfo = new FileInfo(#"D:\Downloads\test_img.png");
// The byte[] to save the data in
byte[] data = new byte[fileInfo.Length];
// Console.WriteLine(fileInfo.Length);
// Load a filestream and put its content into the byte[]
using (FileStream fs = fileInfo.OpenRead())
{
fs.Read(data, 0, data.Length);
}
talk.SetBytes(data);
Thread.Sleep(1000);
}
}
}

Related

Two way communication between Unity and Python

So I want to send and receive from/to Unity and Python in the same run.
I have the following components for the communication.
TCPSendPipe - Sends data from Unity to Python
TCPListePipe - Receives data from Python
Python Script - Send (uses socket.connect) and Receive (uses socket.bind)
At the moment I can only use one at a time either,
TCPSendPipe with Python receive or,
TCPListenPipe with Python send
Following are the scripts:
TCPSendPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using UnityEngine;
public class TCPSendPipe : MonoBehaviour
{
public String Host = "localhost";
public Int32 Port = 55000;
TcpClient mySocket = null;
NetworkStream theStream = null;
StreamWriter theWriter = null;
public GameObject robot;
public Vector3 robPos;
// Start is called before the first frame update
void Start()
{
robot = GameObject.Find("robot");
mySocket = new TcpClient();
if (SetupSocket())
{
Debug.Log("socket is set up");
}
}
// Update is called once per frame
void Update()
{
robPos = robot.transform.position;
Debug.Log(robPos);
if (!mySocket.Connected)
{
SetupSocket();
}
sendMsg();
}
public void sendMsg()
{
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
//Byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes("yah!! it works");
Byte[] sendBytes = procData();
mySocket.GetStream().Write(sendBytes, 0, sendBytes.Length);
}
public bool SetupSocket()
{
try
{
mySocket.Connect(Host, Port);
Debug.Log("socket is sent");
return true;
}
catch (Exception e)
{
Debug.Log("Socket error: " + e);
return false;
}
}
public Byte[] procData()
{
Byte[] bytes = new Byte[12]; // 4 bytes per float
Buffer.BlockCopy( BitConverter.GetBytes( robPos.x ), 0, bytes, 0, 4 );
Buffer.BlockCopy( BitConverter.GetBytes( robPos.y ), 0, bytes, 4, 4 );
Buffer.BlockCopy( BitConverter.GetBytes( robPos.z ), 0, bytes, 8, 4 );
return bytes;
}
private void OnApplicationQuit()
{
if (mySocket != null && mySocket.Connected)
mySocket.Close();
}
}
TCPListenPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Globalization;
using System.Net.Sockets;
using UnityEngine;
public class TCPListenPipe : MonoBehaviour
{
public String Host = "localhost";
public Int32 Port = 55000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
private TcpListener listener = null;
private TcpClient client = null;
private NetworkStream ns = null;
string msg;
// Start is called before the first frame update
void Awake()
{
listener = new TcpListener(localAddr, Port);
listener.Start();
Debug.Log("is listening");
if (listener.Pending())
{
client = listener.AcceptTcpClient();
Debug.Log("Connected");
}
}
// Update is called once per frame
void Update()
{
if (client == null)
{
if (listener.Pending())
{
client = listener.AcceptTcpClient();
Debug.Log("Connected");
}
else
{
return;
}
}
ns = client.GetStream();
if ((ns != null) && (ns.DataAvailable))
{
StreamReader reader = new StreamReader(ns);
msg = reader.ReadToEnd();
float data = float.Parse(msg, CultureInfo.InvariantCulture);
Debug.Log(data);
}
}
private void OnApplicationQuit()
{
if (listener != null)
listener.Stop();
}
}
Python Script
import socket
import struct
import numpy as np
class comm(object):
TCP_IP = '127.0.0.1'
TCP_PORT = 55000
BUFFER_SIZE = 12 # Normally 1024, but we want fast response
conn = []
addr = []
s = []
def connect(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((self.TCP_IP, self.TCP_PORT))
self.s.listen(1)
self.conn, self.addr = self.s.accept()
print ('Connection address:', self.addr)
def receive(self):
byte_data = self.conn.recv(self.BUFFER_SIZE)
pos_data = np.array(np.frombuffer(byte_data, dtype=np.float32));
#print("bytes data:", byte_data)
print ("received data:", pos_data)
#conn.close()
return(pos_data)
def send(self):
cable_length = 25.123
MESSAGE = str(cable_length)
#MESSAGE = cable_length.tobytes()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.TCP_IP, self.TCP_PORT))
#s.send(MESSAGE)
s.send(MESSAGE.encode())
s.close()
return(MESSAGE)
So in order to send data from Unity to Python, I attach the TCPSendPipe.cs to the scene and within python script I just call receive after connecting.
comm_cl = comm()
comm_cl.connect()
while True:
data = comm_cl.receive()
Whereas to send data from Python to Unity, I have to detach TCPSendPipe.cs and attach TCPListenPipe.cs to the scene and within python script I just call send (without connect since connect has socket.bind).
send_data = aa.send()
My purpose is to have a 2 way communication between Unity and Python.
Can I use 2 different sockets to send and receive?, Is it even possible to create and connect to 2 different sockets at the same time?
Any suggestions or ideas on achieveing this is greatly appreciated.
Thank You.
Can I use 2 different sockets to send and receive?, Is it even possible to create and connect to 2 different sockets at the same time?

16bit 16Khz monochannel wav format audio streaming with JavaScript

Please I am not experienced with audio processing, I am trying to record and stream audio from my microphone and send the audio data to a flask server. I have set up the javascript for the recording. The thing is it is for a speech recognition engine and it needs the audio stream to be in 16bit 16Khz monochannel and wav format. I was trying to use recorder.js (https://github.com/mattdiamond/Recorderjs/blob/master/dist/recorder.js) but the context.createScriptProcessor was deprecated so I switched to using the audioworklet processor (https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet). I just took some code from the recorder.js that encodes in wav and another code that downsamples the default 44100 to 16Khz i.e 16000 samples per second. The problem is
1.The bytes I am recieving in the flask server is corrupted ( I tried writing them to a wav file and it is an wav audio that is zero seconds long)
2. I am not sure why but I think its from the javascript code (or the flask I don't know).
If any one knows where I got it wrong, or better still how I can achieve streaming in 16bit 16Khz monochannel and wav format, I would really appreciate. The codes are below.
javascript code using the audioworklet
let dataArray = [];
var recording = true;
const main = async () => {
const context = new AudioContext()
const microphone = await navigator.mediaDevices.getUserMedia({
audio:true
})
let sampleRate = 16000
let numOfChannels = 1
const source = context.createMediaStreamSource(microphone)
await context.audioWorklet.addModule('js/recorderWorkletProcessor.js')
const recorder = new AudioWorkletNode(context, "recorder.worklet")
source.connect(recorder).connect(context.destination)
recorder.port.onmessage = (e) => {
// downsample to 16KHz sample rate
downSampledData = downsampleBuffer(e.data, sampleRate, context.sampleRate)
// convert to audio/wav format
let dataView = encodeWAV(downSampledData, context, sampleRate)
dataArray.push(e.data)
// Create a blob file
let blob = new Blob([ dataView ], { type: 'audio/wav' });
// send to the server
upload(blob)
if (!recording){
console.log("RECORDING STOPPED");
recorder.disconnect(context.destination);
source.disconnect(recorder);
}
}
};
// sorry I am not using this but floatTo16BitPCM()
function convertFloat32To16BitPCM(input) {
const output = new Int16Array(input.length)
for (let i = 0; i < input.length; i++) {
const s = Math.max(-1, Math.min(1, input[i]))
output[i] = s < 0 ? s * 0x8000 : s * 0x7fff
}
return output
}
function startRec () {
// start the recording
main()
}
function stopRec () {
// stop the recording
console.log('stopped')
recording = false
}
// convert to 16Bit PCM
function floatTo16BitPCM(output, offset, input){
for (var i = 0; i < input.length; i++, offset+=2){
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function writeString(view, offset, string){
for (var i = 0; i < string.length; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
}
// convert to wave format
function encodeWAV(samples, context, sampleRate) {
let buffer = new ArrayBuffer(44 + samples.length * 2);
let view = new DataView(buffer);
/* RIFF identifier */
writeString(view, 0, 'RIFF');
/* RIFF chunk length */
view.setUint32(4, 36 + samples.length * 2, true);
/* RIFF type */
writeString(view, 8, 'WAVE');
/* format chunk identifier */
writeString(view, 12, 'fmt ');
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, 1, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, 1 * 2, true);
/* bits per sample */
view.setUint16(34, 16, true);
/* data chunk identifier */
writeString(view, 36, 'data');
/* data chunk length */
view.setUint32(40, samples.length * 2, true);
floatTo16BitPCM(view, 44, samples);
return view;
}
const blobToBase64 = (blob) => {
// convert blob to base64 encoding
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
resolve(reader.result);
};
});
};
const upload = async (audioData) => {
// send the blob containing audio bytes to the flask server
var AjaxURL = 'http://127.0.0.1:5000/media';
const b64 = await blobToBase64(audioData);
const jsonString = JSON.stringify({blob: b64});
console.log(jsonString);
$.ajax({
type: "POST",
url: AjaxURL,
data: jsonString,
contentType: 'application/json;charset=UTF-8',
success: function(result) {
window.console.log(result.response);
}
});
}
function downsampleBuffer(buffer, rate, sampleRate) {
if (rate == sampleRate) {
return buffer;
}
if (rate > sampleRate) {
throw "downsampling rate show be smaller than original sample rate";
}
var sampleRateRatio = sampleRate / rate;
var newLength = Math.round(buffer.length / sampleRateRatio);
var result = new Float32Array(newLength);
var offsetResult = 0;
var offsetBuffer = 0;
while (offsetResult < result.length) {
var nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
// Use average value of skipped samples
var accum = 0, count = 0;
for (var i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
accum += buffer[i];
count++;
}
result[offsetResult] = accum / count;
// Or you can simply get rid of the skipped samples:
// result[offsetResult] = buffer[nextOffsetBuffer];
offsetResult++;
offsetBuffer = nextOffsetBuffer;
}
return result;
}
recorderWorkletProcessor.js
bufferSize = 4096
_bytesWritten = 0
_buffer = new Float32Array(this.bufferSize)
constructor () {
super()
this.initBuffer()
}
initBuffer() {
this._bytesWritten = 0
}
isBufferEmpty() {
return this._bytesWritten === 0
}
isBufferFull() {
return this._bytesWritten === this.bufferSize
}
process(inputs, outputs, parameters) {
this.append(inputs[0][0])
return true
}
append(channelData){
if (this.isBufferFull()){
this.flush()
}
if (!channelData) return
for (let i=0; i < channelData.length; i++){
this._buffer[this._bytesWritten++] = channelData[i]
}
}
flush () {
this.port.postMessage(
this._bytesWritten < this.bufferSize ? this.buffer.slice(0, this._bytesWritten) : this._buffer
)
this.initBuffer()
}
}
registerProcessor('recorder.worklet', RecorderProcessor)
finally my flask server code.
NOTE: The endpoint has to be a http endpoint that is why I am using the ajax call in the JS (not sockets)...There is a speech recognition engine server running on sockets that is why there is a socket call in async in the code. The socket server recieves BYTES of audio data.
#!/usr/bin/env python
# encoding: utf-8
from flask import Flask, jsonify, request
from flask_cors import CORS, cross_origin
import numpy as np
import soundfile as sf
import json
import logging
import base64
import asyncio
import websockets
import sys
import wave
app = Flask(__name__)
app.secret_key = "stream"
CORS(app, supports_credentials=True)
def get_byte_string(string):
delimiter = ';base64,'
splitted_string = string.split(delimiter)
return splitted_string[1]
#app.route('/media', methods=['POST'])
async def echo():
app.logger.info('Connection accepted')
has_seen_media = False
message_count = 0
chunk = None
data = json.loads(request.data)
if data is None:
app.logger.info('No message recieved')
else:
app.logger.info("Media message recieved")
blob = data['blob']
byte_str = get_byte_string(blob)
byte_str = bytes(byte_str, 'utf-8')
chunk = base64.decodebytes(byte_str)
has_seen_media = True
if has_seen_media:
app.logger.info("Payload recieved: {} bytes".format(len(chunk)))
# set up websocket here
async with websockets.connect('ws://localhost:2700') as websocket:
await websocket.send(chunk)
print (await websocket.recv())
await websocket.send('{"eof" : 1}')
print (await websocket.recv())
message_count += 1
return jsonify({'response': ''})
if __name__ == '__main__':
app.logger.setLevel(logging.DEBUG)
app.run(debug=True)

Problem with multiple messages in TCP server [duplicate]

This question already has answers here:
How to properly use recv function for TCP chat, python3?
(1 answer)
How does socket recv function detects end of message
(1 answer)
Closed 1 year ago.
I apologize if this question seems trivial, but I'm a beginner at both C and programming with sockets. Also, english is not my native language.
I recently failed an uni assignment that asked me to implement a TCP server-client in C that accepts both ipv4 and ipv6, in which the client would send messages to add, remove, list and query pairs of ints from a linked list stored in the server. So, I made the server and the client with the codes below (not included are the code for the linked lists and for the function strsplit):
server (servidor.c)
void func(int sockfd)
{
struct Node* posts = NULL;
char client_message[MAX];
char server_message[MAX];
char* str;
char **p;
int X, Y, i, j, k;
int n = 0;
char sX[5];
char sY[5];
for (;;)
{
recv(sockfd, client_message, sizeof(client_message), 0);
printf("> %s", client_message);
strcpy(str, client_message);
p = strsplit(str, " ");
memset(server_message, 0, MAX);
if(strncmp("kill", p[0], 4) == 0)
{
break;
}
else if(strncmp("add", p[0], 3) == 0)
{
if(n == 50)
{
strncat(server_message, "limit exceeded", 14);
}
else
{
strncat(server_message, p[1], 4);
strncat(server_message, " ", 1);
X = atoi(p[1]);
strtok(p[2], "\n");
strncat(server_message, p[2], 4);
strncat(server_message, " ", 1);
Y = atoi(p[2]);
i = push(&posts, X, Y);
if(i == 0)
{
strncat(server_message, "added", 5);
n++;
}
else
{
strncat(server_message, "already exists", 14);
}
free(p);
}
}
else if(strncmp("rm", p[0], 2) == 0)
{
strncat(server_message, p[1], 4);
strncat(server_message, " ", 1);
X = atoi(p[1]);
strtok(p[2], "\n");
strncat(server_message, p[2], 4);
strncat(server_message, " ", 1);
Y = atoi(p[2]);
i = deleteNode(&posts, X, Y);
if(i == 0)
{
strncat(server_message, "removed", 7);
n--;
}
else
{
strncat(server_message, "does not exist", 14);
}
free(p);
}
else if(strncmp("list", p[0], 4) == 0)
{
if(posts == NULL)
{
strncat(server_message, "none", 4);
}
else
{
struct Node *temp = posts;
while(temp != NULL)
{
bzero(sX, 4);
bzero(sY, 4);
snprintf(sX, sizeof(sX), "%d",temp->X);
snprintf(sY, sizeof(sY), "%d",temp->Y);
strncat(server_message, sX, 4);
strncat(server_message, " ", 1);
strncat(server_message, sY, 4);
strncat(server_message, " ", 1);
temp = temp->next;
}
free(temp);
}
}
else if(strncmp("query", p[0], 5) == 0)
{
if(posts == NULL)
{
strncat(server_message, "none", 4);
}
else
{
struct Node *temp1 = posts;
k = 19998;
X = atoi(p[1]);
strtok(p[2], "\n");
Y = atoi(p[2]);
while(temp1 != NULL)
{
i = abs(temp1->X - X);
j = abs(temp1->Y - Y);
i = i + j;
if(i <= k)
{
snprintf(sX, sizeof(sX), "%d",temp1->X);
snprintf(sY, sizeof(sY), "%d",temp1->Y);
k = i;
}
temp1 = temp1->next;
}
strncat(server_message, sX, 4);
strncat(server_message, " ", 1);
strncat(server_message, sY, 4);
strncat(server_message, " ", 1);
free(temp1);
}
}
strncat(server_message, "\n", 1);
printf("%s", server_message);
send(sockfd, server_message, sizeof(server_message), 0);
}
}
int main(int argc, char *argv[])
{
if(strncmp("v4", argv[1], 2) == 0)
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(atoi(argv[2]));
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0)
{
exit(0);
}
if ((listen(sockfd, 5)) != 0)
{
exit(0);
}
len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0)
{
exit(0);
}
func(connfd);
close(sockfd);
}
else if(strncmp("v6", argv[1], 2) == 0)
{
int sockfd, connfd, len;
struct sockaddr_in6 servaddr, cli;
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if(sockfd == -1)
{
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin6_family = AF_INET6;
servaddr.sin6_addr = in6addr_any;
servaddr.sin6_port = htons(atoi(argv[2]));
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0)
{
exit(0);
}
if ((listen(sockfd, 5)) != 0)
{
exit(0);
}
len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0)
{
exit(0);
}
func(connfd);
close(sockfd);
}
return 0;
}
client (cliente.c)
void func(int sockfd)
{
char buff[MAX];
int n;
for (;;)
{
bzero(buff, sizeof(buff));
n = 0;
while ((buff[n++] = getchar()) != '\n')
;
send(sockfd, buff, sizeof(buff), 0);
if ((strncmp(buff, "kill", 4)) == 0)
{
break;
}
bzero(buff, sizeof(buff));
recv(sockfd, buff, sizeof(buff), 0);
printf("> %s", buff);
}
}
int main(int argc, char *argv[])
{
if(strchr(argv[1], ':') != NULL)
{
int sockfd, connfd;
struct sockaddr_in6 servaddr, cli;
struct in6_addr result;
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd == -1)
{
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin6_family = AF_INET6;
inet_pton(AF_INET6, argv[1], &result);
servaddr.sin6_addr = result;
servaddr.sin6_port = htons(atoi(argv[2]));
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0)
{
exit(0);
}
func(sockfd);
close(sockfd);
}
else
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);
servaddr.sin_port = htons(atoi(argv[2]));
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0)
{
exit(0);
}
func(sockfd);
close(sockfd);
}
return 0;
}
Testing on my own, by opening the server and the client in separate terminals and sending messages one by one, the server seemed to be working as intended. However, my professor says otherwise. After failing the assignment, he provided me with the python code of the software used to grade my server, which is as follows:
run_tests.py
def run_basic_tests(exec_path, version, port, msg_type):
address = '127.0.0.1' if version == 'v4' else '::1'
list_dir = os.listdir('tests/in')
list_dir = sorted(list_dir)
for filename in list_dir:
filename = filename.split('.')[0]
_, result_file_path = tempfile.mkstemp()
server = sp.Popen(
[f'exec {exec_path} {version} {port}'], shell=True, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
ret = os.system(
f'python3 client.py {address} {port} {msg_type} < tests/in/{filename}.in > {result_file_path}')
ret = os.WEXITSTATUS(ret)
if ret == 0:
if filecmp.cmp(f'tests/out/{filename}.out', result_file_path, shallow=False):
print(f'{filename}\t[OK]')
else:
print(f'{filename}\t[FAILED] (diff output)')
else:
print(f'{filename}\t[FAILED] (client exited with non-zero code {ret})')
os.remove(result_file_path)
server.kill()
if __name__ == '__main__':
if len(sys.argv) != 3:
print(f'usage: python3 {sys.argv[0]} <server> <port>')
sys.exit(0)
exec_path = sys.argv[1]
port = int(sys.argv[2])
if not exec_path.startswith('/'):
print('provide the full path to the executable')
sys.exit(0)
for address_family in ['v4', 'v6']:
for msg_type in ['single_msg_single_pkg', 'single_msg_multiple_pkg', 'multiple_msg_single_pkg']:
print('Testing IP' + address_family, msg_type)
run_basic_tests(exec_path, address_family, port, msg_type)
client.py
BUFFER = ''
def get_address_family(address):
try:
socket.inet_pton(socket.AF_INET, address)
return socket.AF_INET
except:
pass
try:
socket.inet_pton(socket.AF_INET6, address)
return socket.AF_INET6
except:
pass
sys.exit(1)
def create_socket(address, port):
address_family = get_address_family(address)
attempts = 0
client_socket = None
while attempts < 5:
try:
client_socket = socket.socket(address_family, socket.SOCK_STREAM)
client_socket.connect((address, port))
break
except socket.error:
client_socket = None
time.sleep(0.05)
attempts += 1
if not client_socket:
sys.exit(2)
return client_socket
# send one message
def send(client_socket, msg):
msg = msg.encode('ascii')
total_sent = 0
while total_sent != len(msg):
sent = client_socket.send(msg[total_sent:])
if sent == 0:
sys.exit(3)
total_sent += sent
# receive one complete message
def receive(client_socket):
global BUFFER
while True:
if '\n' in BUFFER:
msg = BUFFER[:BUFFER.index('\n')]
BUFFER = BUFFER[BUFFER.index('\n') + 1:]
return msg
try:
data = client_socket.recv(500 - len(BUFFER)).decode()
except socket.timeout:
sys.exit(7)
if not data:
sys.exit(4)
BUFFER += data
if len(BUFFER) >= 500:
sys.exit(5)
def run_multiple_msg_single_pkg(client_socket):
msg_buffer = []
for msg in sys.stdin:
msg_buffer.append(msg)
for i in range(0, len(msg_buffer), 2):
if i == len(msg_buffer) - 1:
send(client_socket, msg_buffer[i])
if msg_buffer[i] == 'kill\n':
client_socket.close()
sys.exit(0)
ret = receive(client_socket)
print(ret)
else:
msg = msg_buffer[i] + msg_buffer[i + 1]
send(client_socket, msg)
if msg_buffer[i] == 'kill\n':
client_socket.close()
sys.exit(0)
ret = receive(client_socket)
print(ret)
if msg_buffer[i + 1] == 'kill\n':
client_socket.close()
sys.exit(0)
ret = receive(client_socket)
print(ret)
def run_single_msg_multiple_pkg(client_socket):
for msg in sys.stdin:
send(client_socket, msg[:3])
time.sleep(0.1)
send(client_socket, msg[3:])
if msg == 'kill\n':
client_socket.close()
sys.exit(0)
ret = receive(client_socket)
print(ret)
def run_single_msg_single_pkg(client_socket):
for msg in sys.stdin:
send(client_socket, msg)
if msg == 'kill\n':
client_socket.close()
sys.exit(0)
ret = receive(client_socket)
print(ret)
if __name__ == '__main__':
if len(sys.argv) != 4:
print(
f'Usage: python3 {sys.argv[0]} <address> <port> [single_msg_single_pkg | single_msg_multiple_pkg | multiple_msg_single_pkg]')
sys.exit(6)
client_socket = create_socket(sys.argv[1], int(sys.argv[2]))
client_socket.settimeout(5)
if sys.argv[3] == 'single_msg_single_pkg':
run_single_msg_single_pkg(client_socket)
elif sys.argv[3] == 'single_msg_multiple_pkg':
run_single_msg_multiple_pkg(client_socket)
elif sys.argv[3] == 'multiple_msg_single_pkg':
run_multiple_msg_single_pkg(client_socket)
client_socket.close()
sys.exit(0)
Running my code with this software, none of the tests work. Basically, after receiving and sending the first message, my server halts communication with the client, failing every single test. This has probably something to do with how I'm treating the strings on my code, but honestly I'm at a loss here. Can someone at least give me a nudge in the right direction?
The main problem is that string that is send from python test application is not null-terminated, but you assume it is.
Here in python:
msg = msg.encode('ascii')
msg is encoded in ASCII format, but encode() method returns a bytes object which is not null-terminated, but when you receive it in your server:
recv(sockfd, client_message, sizeof(client_message), 0);
printf("> %s", client_message);
strcpy(str, client_message);
You have codes in your code that has assumed that what you have received in client_message is a null-terminated string. If you have zeroed client_message before recv(), you probably will not see this problem.
Bugs that I see in your code:
You assumed that messages are null-terminated. But it seems that they are supposed to be \n separated.
always check return of recv. you need to handle return values correctly. you may get error or you may get part of whole data.
In addition, run recv loop in a thread. although a suggestion, you normally always want to do this.

Can't connect to a socket in cs go

I am coding a cs go plugin for its connectivity with discord, so I could do the remote bans.
I have this code on the socket receive:
public OnWebsocketReceive(WebsocketHandle:websocket, WebsocketSendType:iType, String:receiveData[], dataSize)
{
new bool:IsArray;
new String:fetch[16];
strcopy(fetch, 16, receiveData);
if (!StrEqual(fetch, "{", true))
{
IsArray = true;
}
if (IsArray)
{
if (StrContains(receiveData, "RequestType", false) != -1)
{
new JSON_Object:obj = json_decode(receiveData, JSON_Object:0, 0, 0);
new RTYPE = JSON_Object.GetInt(obj, "RequestType");
switch (RTYPE)
{
case 452:
{
// Some stuff here
}
default:
{
}
}
}
}
return 0;
}
And this code on socket init:
OpenSocketStream()
{
new String:serverIP[40];
new longip = GetConVarInt(FindConVar("hostip"));
FormatEx(serverIP, 40, "%d.%d.%d.%d", longip >>> 24 & 255, longip >>> 16 & 255, longip >>> 8 & 255, longip & 255);
if (!ServerSocket)
{
ServerSocket = Websocket_Open(serverIP, GetConVarInt(CVAR_WebsocketPort), OnWebsocketIncoming, OnWebsocketMasterError, OnWebsocketMasterClose);
}
return 0;
}
public Action:OnWebsocketIncoming(WebsocketHandle:websocket, WebsocketHandle:newWebsocket, String:remoteIP[], remotePort, String:protocols[256])
{
Format(protocols, 256, "");
Websocket_HookChild(newWebsocket, OnWebsocketReceive, OnWebsocketDisconnect, OnChildWebsocketError);
PushArrayCell(ClientSockets, newWebsocket);
return Action:0;
}
And my python code to connect to the socket:
import socket
import json
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
x = '{"RequestType":"452","RemoteLinkPKG":"POST","RemoteLinkPKG":"1337","SID":"1234","Time":"1234","Action"."1"}'
y = json.dumps(x)
s.connect(('serverip',4126))
s.send(y)
print s.recv(1024)
But it just hangs up and I get no reply

cv2 incorrect image decode

I'm programming a Java client which sends an image as byte array and a Python server to receive the image. Received image height, width, channels are right,
sock = socket.socket()
sock.bind(('localhost', 8080))
sock.listen(1)
print ("Listen")
conn, addr = sock.accept()
print('Start server')
while True:
data = conn.recv(1024)
if not data:
break
img = cv2.imdecode(np.fromstring(io.BytesIO(data).getvalue(), dtype=np.uint8), 1)
np.save('snapshot.npy',img)
exit()
Showing the image using cv2.imshow('img', img) gives an incorrect result:
Java side:
public class Client implements Runnable {
private Socket socket;
private DataOutputStream out;
private String server;
private int port;
private ArrayList<ResponseListener> listeners = new ArrayList<>();
public void addListener(ResponseListener responseListener){
listeners.add(responseListener);
}
public void removeListeners(ResponseListener responseListener){
listeners.remove(responseListener);
}
Client(String server, int port) {
this.server = server;
this.port = port;
}
public void start(){
while(socket==null){
try {
socket = new Socket(server, port);
socket.setTcpNoDelay(true);
System.out.println("Ready");
listeners.forEach((listener)->listener.serverIsReady());
} catch (Exception ex) {
System.out.println("In thread " + ex.toString());
}
}
}
public void send(byte[] img) throws IOException {
out.write(img);
}
#Override
public void run() {
InputStreamReader in = null;
try {
in = new InputStreamReader(socket.getInputStream());
System.out.println(in);
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
System.out.println("in or out failed");
System.exit(-1);
}
int count = 0;
while (true) {
try {
int line = in.read();
count++;
if(count==4) {
listeners.forEach((listener)->listener.onSignDefined(String.valueOf(line)));
count=0;
}
} catch (Exception e) {
System.out.println("In loop " + e.toString());
System.exit(-1);
}
}
}
}
I solved problem. Solution really easy:
data = conn.recv(640*480*3)
640*480*3 - size of image

Categories