Socket ile gelen verileri değişkenlere nasıl atarım?

client den gelen bilgileri sunucudaki değişkenlere atamak istiyorum. Resim ve metin gönderiyorum.

#server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1236))
s.listen(5)
c, addr = s.accept()
image_datas, d1, d2 = c.recv(1024) 
f = open("C:\\Users\\SD\\Desktop\\image.jpg", "wb")
while image_datas:
    f.write(image_datas)
    image_datas = c.recv(1024)
print(d1,d2)
f.close()
c.close()
s.close()
#client.py
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("localhost", 1236))
f = open("image.jpg", "rb")
img_data = f.read()
data1 = "hello"
data2 = "server"
c.send(img_data,data2,data3)
f.close()
c.close()

Bu soruyu daha önce sormuşum, ama sorunu çözemedim.

1 Beğeni

Bu konuda yardım edebilecek yok mu? yoksa bu socket de yapılmıyor mu?

1 Beğeni

Aşağıdaki kodları inceleyin isterseniz:
server.py

import socket
import pickle

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1236))
s.listen(5)

c, addr = s.accept()

data = b""

while True:
    recv = c.recv(4096)
    if not recv:
        break
    data += recv
        
loads = pickle.loads(data)
print(loads[0], loads[1])
with open("test2.mp3", "wb") as f:
    f.write(loads[-1])
    
s.close()

client.py

import socket
import pickle

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

with open("test.mp3", "rb") as f:
    data1 = f.read()
    data2 = "hello"
    data3 = "server"
    data = pickle.dumps((data1, data2, data3))
    c.send(data)

c.close()

Kodları inceledim ve çalıştırdım, sonra threading modülünü de ekledim ama client bağlanıp resmi gönderince server resmi kayıt etmesi için cliet’in çıkmasını bekliyor. Yani client bir kez bağlanmış oluyor ve başka mesaj gönderemiyor, mesaj alamıyor.

#server.py
import socket, pickle, threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1234))
s.listen(5)
print("server çalışıyor...")

def func(con, d):
	loads = pickle.loads(d)
	with open("resim.jpg","wb") as f:
		f.write(loads[0])
	f.close()
	con.send(b"resim kaydedildi.")


while True:
	con, adr = s.accept()
	print(adr,"baglandı...")
	datas = b""
	while True:
		recv = con.recv(4096)
		if not recv:
			break
		datas += recv
	threading.Thread(target = func, args = (con, datas)).start()
import socket, pickle
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(("localhost", 1234))

while True:
	data2 = input("> ")
	data3 = input("> ")
	with open("deneme.jpg", "rb") as f:
		data1 = f.read()
		data = pickle.dumps((data1,data2,data3))
		c.send(data)
	f.close()
	client_data = c.recv(1024)
	print(client_data.decode())

Bunu cok yakinda bir SSS yapabilirim:

SOCK_STREAM adi ustunde bir veri akisi yaratiyor. Bir taraftan yapilan send cagrilari diger taraftaki recv'lere tekabul etmek zorunda degil, garanti edilen tek sey bir taraftan yollanan byte’larin diger taraftan ayni sirayla alinmasi.

Bunun uzerine herhangi bir protokol insa etmek icin akisi parcalara bolmek gerekiyor. Bunun en basit yontemleri:

{onceden tanimli uzunlukta 1. parca}{onceden tanimli uzunlukta 2. parca}...

veya

{1. parca}{ayrac}{2. parca}{ayrac}...

veya

{1. parcanin sabit uzunlukla ifade edilen boyu}{1. parcanin geri kalani}{2. parcanin sabit uzunlukla ifade edilen boyu}{2. parcanin geri kalani}...

seklinde veri yollayip almak. OOB veri veya spesifik TCP implementasyonlariyla yapilabilecek hack’lere deginmiyorum, onlari kullanmak ve pratikteki network katmanlarindan gecirmek cok daha zor.

1 Beğeni

Bende temel network bilgileri yok, o yüzden kod üstünde anlatsanız benim için daha anlaşılır olur.

Bu arada aşağıdaki kodları inceleyin, @aib’in söylemeye çalıştığı şey, önce göndereceğiniz verinin uzunluğunu gönderin, recv fonksiyonuna yazılacak sayı sabit bir sayı değil de sürekli değişen verinin uzunluğu olsun.

server.py

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

import os
import socket
import pickle
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1235))
s.listen(5)

connections = []


def accept():
    c, addr = s.accept()
    connections.append([c, addr, True])


def receive(c):
    if c[2]:
        c[2] = False
        length = c[0].recv(1024).decode("utf-8")
        data = b""
        while True:
            try:
                recv = c[0].recv(int(length))
            except ValueError:
                return
            data += recv
            if len(data) == int(length):
                break
        loads = pickle.loads(data)
        name, ext = os.path.splitext(loads[2])
        count = len([i for i in os.listdir(".") if i.startswith(name)])
        with open(f"{name}{count}{ext}", "wb") as f:
            f.write(loads[0])
        print(loads[1])
        c[2] = True
            
    
while True:
    t1 = threading.Thread(target=accept, daemon=True)
    t1.start()
    t1.join(1)
    
    if connections:
        for i in connections:
            t2 = threading.Thread(
                target=lambda: receive(c=i),
                daemon=True
            )
            t2.start()
            t2.join(1)

client.py

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

import time
import socket
import pickle

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

while True:
    path = input("Dosya yolu: ")
    with open(path, "rb") as f:
        data1 = f.read()
        data2 = input("Mesaj: ")     
        data = pickle.dumps((data1, data2, path))
        c.send(str(len(data)).encode("utf-8"))
        time.sleep(2)
        c.send(data)

Not: Kodları değiştirdim, birden çok kullanıcı, birden çok dosya gönderebilirler.

Peki sunucu karşı tarafa bir bilgilendirme mesajı nasıl gönderir?
bende bu hatayı verdi:

s.send(b"resim kaydedildi...")
OSError: [WinError 10057] Yuva bağlı olmadığından ve (bir veri birimi yuvasında bir sento çağrısı kullanırken) adres sağlanmadığından bir veri gönderme veya alma isteğine izin verilmedi

Mesaj gönderme şekli aynı.
Bende hata vermedi. Siz nasıl değişiklikler yaptınız? Bu arada kodları son dakikalarda değiştirdim, acaba son düzeltilen kodları mı kullandınız yoksa düzeltilmeden önceki kodları mı? Bu arada PORT numarası birinde 1234 diğerinde 1235’miş, onu da düzelttim. Bir daha bakın.

bu şekilde ayarladım.

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

import os
import socket
import pickle
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1234))
s.listen(5)

connections = []


def accept():
    c, addr = s.accept()
    connections.append([c, addr])


def receive(c, active: bool):
    global index
    if active:
        active = False
        length = c.recv(1024).decode("utf-8")
        data = b""
        while True:
            try:
                recv = c.recv(int(length))
            except ValueError:
                return
            data += recv
            if len(data) == int(length):
                break
        loads = pickle.loads(data)
        with open("resim.jpg", "wb") as f:
            f.write(loads[2])
        s.send(b"resim kaydedildi...")
        index = 0
            
            
status = [True, False]
index = 0
    
while True:
    t1 = threading.Thread(target=accept, daemon=True)
    t1.start()
    t1.join(1)
    
    if connections:
        for i in connections:
            t2 = threading.Thread(
                target=lambda: receive(c=i[0], active=status[index]),daemon=True)
            t2.start()
            t2.join(1)
            index = 1
#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

import time
import socket
import pickle

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

while True:
    data1 = input("Dosya yolu: ")
    data2 = input("Mesaj: ") 
    with open("asd.jpg", "rb") as f:
        data3 = f.read()          
        data = pickle.dumps((data1, data2, data3))
        c.send(str(len(data)).encode("utf-8"))
        time.sleep(2)
        c.send(data)
        c_data = c.recv(1024)
        print(c_data.decode())

Değiştirilmiş kodları önce hiç değiştirmeden kullanın. Sonra da değişikliğinizi yapın bir daha deneyin.

kodlar çalışıyor ama client tarafına bir mesaj gönderilmiyor ki.

Nasıl gitmiyor? Bende niye gidiyor? Aşağıdaki kodları çalıştırın.
server.py

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

import os
import socket
import pickle
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1235))
s.listen(5)

connections = []


def accept():
    c, addr = s.accept()
    connections.append([c, addr, True])


def receive(c):
    if c[2]:
        c[2] = False
        length = c[0].recv(1024).decode("utf-8")
        data = b""
        while True:
            try:
                recv = c[0].recv(int(length))
            except ValueError:
                return
            data += recv
            if len(data) == int(length):
                break
        loads = pickle.loads(data)
        name, ext = os.path.splitext(loads[2])
        count = len([i for i in os.listdir(".") if i.startswith(name)])
        with open(f"{name}{count}{ext}", "wb") as f:
            f.write(loads[0])
        print(loads[1])
        c[2] = True
        c[0].send("Dosya başarıyla indirildi.".encode("utf-8"))

            
    
while True:
    t1 = threading.Thread(target=accept, daemon=True)
    t1.start()
    t1.join(1)
    
    if connections:
        for i in connections:
            t2 = threading.Thread(
                target=lambda: receive(c=i),
                daemon=True
            )
            t2.start()
            t2.join(1)

client.py

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

import time
import socket
import pickle

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

while True:
    path = input("Dosya yolu: ")
    with open(path, "rb") as f:
        data1 = f.read()
        data2 = input("Mesaj: ")     
        data = pickle.dumps((data1, data2, path))
        c.send(str(len(data)).encode("utf-8"))
        time.sleep(2)
        c.send(data)
        recv = c.recv(1024).decode("utf-8")
        print(recv)
2 Beğeni

Bu kodlar ilk attığınız da yok ama.

Sonradan ekledim.

Siz o kodlarda mesajı c ismi ile gönderecekken, s ismi ile göndermeye kalkmışsınız.

Yanlış görmüşüm. :slight_smile: cevapladığınız için teşekkür ederim.

:slight_smile: Neyse, rica ederim, kolay gelsin. İyi geceler.

1 Beğeni

Bu ucuncu yontem.

Ama bu sekilde yapilamaz. recv'in 1024 byte dondurmesi garanti degil cunku. (0 bile dondurebiliyor.)

1 Beğeni

Peki nasıl bir kod yazılmasını önerirsin, kodlarda değişiklik yapalım, daha uygun bir hale getirelim.