Soket Programlama 2
Soket programlama 1 konusunun devamıdır.Kodlarımızı yazmaya başlayalım;
ilk başta bir port numaramızı belirtmeliyiz ;
#define PORT 3333
şimdi bir soket oluşturalım
int soketmaygun ;//Bildiğiniz gibi soketler bir tamsayıdır
soketmaygun = socket(AF_INET,SOCK_STREAM,0);//Soketimizi socket() fonksiyonu ile oluşturuyoruz
if (maygun < 0)//Eğeer bir değer atanmamışsa programımızı kapatıyoruz
{
printf(“Soket oluşurken bir hata oluştu
“);
exit (1);
}
// Fonksiyonumuzdaki parametleri tanımıyoruz tanıştırayım sizi
İlk parametre protokol türünübelirler hazırda 5 protkol vardır
/*
AF_UNIX (UNIX internal protocols)
AF_INET (ARPA Internet protocols)
AF_ISO (ISO protocols)
AF_NS (Xerox Network Systems protocols)
AF_IMPLINK (IMP “host at IMP” link layer)
*/
http://www.google.com.tr/
Tabi bu kadar fonksiyon kullanıyoruz bunlar standart kütüphanelerde yok
<sys/types.h> ve <sys/socket.h> kütüphaneleri kullanacağız.
if(bind(soketmaygun,(struct sockaddr *)& my_addr,size of(struct sockaddr))== -1)
{
printf(“bind”);
exit(1);
}
//bind() fonksiyonu soketi, verilen socket ismi ile ilişkilendirip yerel adres atamasını yapar.
if (listen(soketmaygun, BACKLOG) == -1)
{
perror(“listen”);
exit(1);
}
/*listen() fonksiyonu ile oluşturduğumuz soketi dinlemeye geçeriz. Artık istemciden bağlantı olunca accept() fonksiyonunu çağıracağıznci parametre kaç tane bağlantıyı kuyrukta tutacağımızı belirler. Tamsayı bir değerdir.*/
Program gerekiği sunucunun çalıştığı bilgisayarın adresi veya sunucuya bağlanan istmcilerin adresleri gerekli olabilir. Bu durunda hazır olarak verilen sockaddr_in yapısı kullanılır.
#define PORT 2222
struct sockaddr_in server_addr; /* Server adres bilgisi */
server_addr.sin_family = AF_INET; /* Adres ailesi */
server_addr.sin_port = htons(PORT); /* PORT numarasi */
server_addr.sin_addr.s_addr = INADDR_ANY; /* IP numarasi */
//Bu kodlar kendi adres bilgilerimizi elde etmek içindir. Şu an yazdığımız programın sunucu olduğuna dikkat edin.
Şimdide sunucumuza bağlanan kişinin adresini tespit edelim ;
int accept(int s, struct sockaddr *addr, int *addrlen);
Bağlantının Kabul Edilmesi
//Bizim programla bağlantı kurulduğunda bağlantıyı kabul etmemiz için accept() fonksiyonunu çağırmamız gerekir.
int fd, client_size;
struct sockaddr_in client_addr; /* Client adres bilgisi */
client_size = sizeof(struct sockaddr_in);
fd = accept(soketmaygun, (struct sockaddr *)&client_addr, &client_size));
printf(“%s sunucumuza baglandi…\n”,inet_ntoa(client_addr.sin_addr));
/*accept()’ in ilk argumenti daha önce socket() ile oluşturduğumuz, bind() ile adresini atadığımız ve listen() ile dinlemeye geçtiğimiz soketin ismidir. İkinci parametre karşı tarafın adresinin atanacağı değişken, üçüncü parametre ise adres bilgisinin toplam uzunluğudur.*/
Veri Gönderme
Bir soketten istemciye veri göndermek için send() veya write() fonksiyonları kullanılır.Ben kodlarda send() i kullandım.
int send(int s, const void *msg, int len, unsigned int flags);
Kullanım şekli şöyledir ;
send(fd,mesaj,sizeof(mesaj), 0);
Tüm kodlar ise şöyle olacak ;
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define PORT 3333 /* PORT numarasi */
main(int argc, char *argv[])
{
int ssoketmaygun, fd;
struct sockaddr_in server_addr, client_addr;
int client_size;
char mesaj[32];
printf(“%s %d portu uzerinde calismaya basladi…\n”,argv[0],PORT);
if ((soketmaygun = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf(“Error : socket”);
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(soketmaygun, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
printf(“Error : bind”);
exit(1);
}
if (listen(soketmaygun, 1) == -1)
{
printf(“Error : listen”);
exit(1);
}
while(1)
{
client_size = sizeof(struct sockaddr_in);
if ((fd = accept(soketmaygun, (struct sockaddr *)&client_addr, &client_size)) == -1)
{
printf(“Error : accept”);
continue;
}
printf(“%s sunucumuza baglandi…\n”,inet_ntoa(client_addr.sin_addr));
strcpy(mesaj,”Sunucuma baglantiniz yapildi…\n”);
if (!fork())
{
if (send(fd,mesaj,sizeof(mesaj), 0) == -1) perror(“Error : send”);
close(fd);
exit(0);
}
close(fd);
while ( waitpid(-1,NULL,WNOHANG) > 0);
}
} //Derlendi sorunsuzca çalışıyor foruma eklerken bazı hatalr oluşabilir düzenleyiniz
Şimdiye kadar hep sunucumuzu tasarladık sırada istemci(client)i oluşturmada;
Fonksiyonlar tamamen farklı çünkü biri istemci biri sunucu
#define PORT 2222
// Portumuzu tanımlıyoruz
int main(int argc, char *argv[])
{
if (argc != 2) {
printf(“Kullanimi : %s hostname\n”,argv[0]);
exit(1);
}
//Sunucunun çalıştığı bilgisayar istemciye parametre olarak verilecek
struct hostent *h_name;
if(argc > 1)
{
h_name = gethostbyname(argv[1]);
}
else
{
printf(“Kullanimi: %s hostname\n”,argv[0]);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = *(u_long *) h_name->h_addr;
serv_addr.sin_port = htons(PORT);
printf(“Sunucu adresi: %s\n”,inet_ntoa(serv_addr.sin_addr));
//Parametre olarak alınan host ismini çözümlüyoruz. Adres yapısında olan server_addr değişkeninin PORT numarasını ve IP adresini atıyoruz.
struct hostent *h_name;
if(argc > 1)
{
h_name = gethostbyname(argv[1]);
}
else
{
printf(“Kullanimi: %s hostname\n”,argv[0]);
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = *(u_long *) h_name->h_addr;
serv_addr.sin_port = htons(PORT);
printf(“Sunucu adresi: %s\n”,inet_ntoa(serv_addr.sin_addr));
//Artık hizmetkarımıza, yani sunucumuza bağlanıp selam verme vakti geldi.
if( (soketmaygun = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror(“Hata: soket acilamadi!\n”);
if(connect(soketmaygun, (struct sockaddr *) &serv_addr, sizeof(serv_addr))< 0)
printf(“Hata: sunucuya baglanilamadi!\n”);
while(1)
{
printf(“\n==========================================\n”);
printf(“Mesajinizi girin veya \\”quit\\” yazarak cikin: “);
gets(buf);
printf(“\n”);
if(strcmp(buf,”quit”)==0) break;
if( (send(soketmaygun, buf, sizeof(buf), 0)) <= 0)
printf(“Client: Send error\n”);
strcpy(buf, “”);
if( (recv(sockfd, buf, sizeof(buf), 0)) <= 0)
printf(“Hata: paket alirken bir hata olustu!\n”);
if(buf[0] != 4)
{
printf(“Sunucu’dan gelen mesaj: %s”, buf);
}
else
{
break;
}
}
shutdown(sockfd, 2);
close(sockfd);
/*Aynen sunucu programda olduğu gibi soket açtık. Soket türümüz yine SOCK_STREAM. Sonra connect()fonksiyonunu kullanarak açtığımız soket üzerinden bir bağlantı yaptık. connect() fonksiyonu sys/types.h başlık dosyasında aşağıdaki gibi tanımlanmıştır:
int connect(int s, const void *addr, int addrlen);
lk parametre soket tanımlayıcısı, ikinci parametre bağlantı kurulacak sunucunun adres bilgilerini içeren server_addr yapısı, son parametre ise adres yapısının boyutudur.
*/
/* sunucumuzla aramızda stream bir soket bağlantısı kurmuş olduk. İstemci tarafında connect() yapıldığı zaman, sunucu tarafında accept() yapılır. Yani yapılan bağlantı kabul edilir. Daha önce yazdığımız sunucu programdaki accept() işlemi, telnet programının connect() isteğini karşılıyordu. Şimdi bizim istemimiz bu isteği gönderecek. Dikkat ederseniz ilkel bir telnet programı yazıyoruz.*/
Sunucuya Bilgi Gönderme
. Ekrandan bir mesaj alıp bunu send() fonksiyonu ile sunucuya gönderiyoruz. Bu fonksiyon, dosyalara yazmak için kullandığımız write() fonksiyonu gibidir. send() ile sokete veri gönderiyoruz. Soket sunucu ile bağlantılı olduğundan veri, sunucuya ulaşır. Sunucu ise her send() isteğine recv() ile karşılık verir. send() yada recv() işlemleri her iki tarafta da yapılabilir. Sunucudan gelen her send() isteğine karşı da istemci de bir recv() vardır. Örneğin ftp programında karşılık send() ve recv() işlemleri vardır. Siz önce istemci tarafından ’get dosya’ komutunu göndererek dosya isteğinizi belirtiyorsunuz. Sunucu bu komutu okuyup yorumluyor ve size dosyayı ftp protokolune uygun paketler halinde gönderiyor. Artık siz okumaya başlıyorsunuz. Paketleri alıp birleştirip yerel diske yazıyorsunuz. Bu aşamadan sonra istediğinizi yaptırabilirsiniz.