Socket aynı anda string ve byte gönderme

TypeError: sequence item 6: expected str instance, bytes found hatasını aldım.
araştırıp anladığım anladığım kadarıyla Servera string gönderirken byte kodu gönderdigim için hata verdi.

data = "\n",b" ".join(("k",image_data))

bu şekilde hepsini byte olarak gönderim ama bu seferde tam tersini verdi. Yani hem string hemde byte anda gönderebilir miyim, yoksa başka bir yolu var mı? bu arada gönderidigim byte resim dosyası.

Ne yapınca?

Birden fazla nesne yollamak için, daha doğrusu Python nesnelerini yollamak için pickle modülü var. rencode modülünü de önerebilirim.

Hatanın sebebi de bir str ile bytes’ı toplamaya çalışmanız büyük ihtimalle.

Toplamadım, sadece metinleri gönderirken resim dosyasını da yanında gönderiyorum.

Yanında nasıl gönderebiliyorsunuz?

Böyle;

			f = open(img_path, "rb")
			img_data = f.read()
			f.close()
			data = "\n".join(("a","b","c","d","e",img_data))
			clientSocket.send(data)
			dataFromServer = clientSocket.recv(1024)

join metodu da string’leri toplamıyor mu zaten?

join metodunu siz bana dediniz diye kullanmışdım, nasıl gönderdigini hiç bilmiyorum.

pickle modülünü join ile nasıl kullanabilirim?
zaten verileri sockete tek tek gönderebilsem join’i kullanmazdım.

Hatırladım. join metodunun bütün parametreleri str olmalı, sonuçta onları birleştiriyor.

Gerek yok:

>>> import pickle
>>> veri = pickle.dumps(("a", "b", "c", b"resim dosyasi"))
>>> veri
b'\x80\x04\x95 \x00\x00\x00\x00\x00\x00\x00(\x8c\x01a\x94\x8c\x01b\x94\x8c\x01c\x94C\rresim dosyasi\x94t\x94.'
>>> pickle.loads(veri)
('a', 'b', 'c', b'resim dosyasi')

Peki bunu terardan servar da ayırabilir miyim?

Örneği incelerseniz en son ayırıyor, bunu başka cihazlarda da yapabilirsiniz. Evet.

peki burada direk ismi yerine değişken varsa bayt’ı nasıl kullanabilirim?
ve verileri gönderince client donuyor.

Herzamanki gibi, değişkeni oraya yazacaksınız.

Veri gönderdiği için donacağını sanmıyorum.

hatayı ve modülü anlamam için başka bir dosya açıp oradan deniyim. :slight_smile:

hata aldım.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#server.py

import socket, os, pickle

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1236))
s.listen(10)
while True:
    c, addr = s.accept()
    datas = c.recv(1024)
    a, b = pickle.loads(datas)
    print(a,b)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#client.py
import socket,pickle

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("localhost", 1236))

f = open("image.jpg", "rb")
data = f.read()


veri = pickle.dumps(("k",data))
c.send(veri)
f.close()

aldıgım hata;

    a, b = pickle.loads(datas)
_pickle.UnpicklingError: pickle data was truncated

data kısmını byte mı çevircez?

Server yollanan verinin tamamını tek seferde alamıyor. recv in içine büyük bir sayı yazılabilir ama asıl çözüm mesajların başında verinin uzunluğunun gönderildiği bir protokol yazmak. Server kaç byte veri alması gerektiğini anlar bu sayede.

Doğru dediniz ama onu yapmaya çalıştım, ama kısır döngü gibi bir şey oldu. Sonuç olarak aşağıdaki kodlar çalışıyor, ama sizin dediğiniz şeyi yapabileceğimi sanmıyorum, dediğinizi çalıştırmak için bir fikriniz var mı?

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#server.py
import socket,os,pickle
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1234))
s.listen(10)
c, addr = s.accept()

datas = c.recv(300000)
uzunluk, img_datas = pickle.loads(datas)
print(uzunluk)
f = open("C:\\Users\\SD\\Desktop\\{}.jpg".format("resim"), "wb")
f.write(img_datas)
f.close()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#client.py
import socket,os,pickle
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 1234))
f = open("deneme.jpg", "rb")

img = f.read()
uzunluk = len(pickle.dumps(img))
data = pickle.dumps((uzunluk,img))
s.send(data)
f.close()

socket uzerine protokol tasarlanmasi gereken alt seviye bir arayuze erisim saglayan bir modul. Bu forumda neden bu kadar populer anlayabilmis degilim, sanirim alternatiflerden bahsedilmedigi icin. Simdiye kadar gordugum orneklerin hepsi RPC veya benzeri bir mesajlasma kutuphanesiyle cok rahat cozuluyor:

socket.io var, web aplikasyonlariyla da konusabiliyor.
Python’un xmlrpc'si varmis, ornekleri de basit duruyor.


Neyse, buradaki sorunu ve cozumunu @EkremDincel cok iyi aciklamis.

Ve hayir, pickle string’inin uzunlugunu belirten sayi pickle string’inin bir parcasi olamaz.

Dogrusu uzunlugu sabit uzunlukta bir sayi olarak yollayip datayi ardindan yollamak.

4hede5hodo!6868byte’likPickleDatasi#@$*~~…4141_byte’lik_pickle_datasi_xxx…

gibi. Uzunlugu encode etmek icin struct kullanabilirsin. !H veya !L tavsiye ediyorum.

2 Beğeni

bizimde server-client iletişimi yapması gereken bir proje var acaba xmlrpc kullanabilir miyiz?