> "out of band data" : "OOB Verisi (Out-Of-Band Data)" bazı "stream" protokollerinde olan bir özelliktir. Örneğin "TCP" protokolü "OOB" verisini 1 "byte" olarak desteklemektedir. "OOB" verisine "TCP" de "Acil (Urgent)" veri de denilmektedir. Bunun amacı "OOB" verisinin normal "stream" sırasında değil, daha önce gönderilenlerin (eğer hedef "host" ta henüz onlar okunmamışsa) önünde ele alınabilmesidir. Yani biz "TCP" de birtakım verileri gönderdikten sonra "OOB" verisini gönderirsek, bu veri önce göndermiş olduklarımızdan daha önde işleme sokulabilir. Böylece "OOB" verisi uygulamalarda önce gönderilen birtakım bilgilerin iptal edilmesi gibi gerekçelerle kullanılabilmektedir. Diğer yandan "OOB" verisini gönderebilmek için, -> "send" fonksiyonunun "flags" parametresine "MSG_OOB" bayrağını girmek gerekir. Tabii "TCP" yalnızca 1 "byte" uzunluğunda "OOB" verisinin gönderilmesine izin vermektedir. Bu durumda eğer "send" ile birden fazla bayt "MSG_OOB" bayrağı ile gönderilmek istenirse gönderilenlerin yalnızca son baytı "OOB" olarak gönderilir. Son bayttan önceki tüm baytlar normal veri olarak gönderilmektedir. adımlarını takip etmeliyiz. "OOB" verisini almak için de, -> Normal olarak "OOB" verisi, "recv" fonksiyonunda "MSG_OOB" bayrağı ile alınmaktadır. Ancak bu bayrak kullanılarak "recv" çağrıldığında, eğer bir "OOB" verisi sırada yoksa, "recv" başarısız olmaktadır. "recv" fonksiyonunun "MSG_OOB" bayraklı çağrısında başarılı olabilmesi için o anda bir "OOB" verisinin gelmiş olması gerekir. Pekiyi OOB verisinin geldiğini nasıl anlarız? İşte tipik yöntem "SIGURG" sinyalinin kullanılmasıdır. Çünkü sokete bir "OOB" verisi geldiğinde işletim sistemi, "SIGURG" sinyali oluşturabilmektedir. Çünkü varsayılan durumlarda, "OOB" verisi geldiğinde, sinyal gönderilmemektedir. Bunu kesinleştirmek için şu adımları takip etmeliyiz; -> soket üzerinde "fcntl" fonksiyonu ile "F_SETOWN" komut kodunu kullanarak "set" işlemi yapmak gerekir. "fcntl" fonksiyonunun son parametresi bu durumda sinyalin gönderileceği prosesin "ID" değeri olarak girilmelidir. Eğer bu parametre negatif bir "Process Group ID" olarak girilirse, bu durumda işletim sistemi, o proses grubunun bütün üyelerine bu sinyali gönderecektir. Tabii tipik olarak sinyalin soket betimleyicisine sahip olan prosese gönderilmesi istenir. Bu işlem ise if (fcntl(sock_client, F_SETOWN, getpid()) == -1) exit_sys("fcntl"); çağrısı ile gerçekleştirilebilir. Diğer yandan "SIGURG" sinyalinin varsayılan davranışı da "IGNORE" biçimindedir. Yani ilgili proses eğer bu sinyali "set" etmemişse sanki sinyal oluşmamış gibi bir davranış gözükür. Dolayısıyla "SIGURG" sinyalini de "set" etmeliyiz. Aşağıdaki bu konuya ilişkin bir örnek verilmiştir. * Örnek 1, Aşağıdaki "server" programda bir "OOB" verisi geldiğinde "SIGURG" sinyali oluşturulmaktadır. Bu sinyalin içerisinde "recv" fonksiyonu "MSG_OOB" bayrağı ile çağrılmıştır. "OOB" verisinin okunması için "MSG_OOB" bayrağı gerekir. Ancak "OOB" verisinin olmadığı bir durumda bu bayrak kullanılırsa "recv" başarısız olmaktadır. O halde "SIGURG" sinyali geldiğinde "recv" fonksiyonu "MSG_OOB" bayrağı ile çağrılmalıdır. Bu durumda "TCP" de her zaman yalnızca 1 bayt okunabilmektedir. Ayrıca "server" programda "SIGURG" sinyali "set" edilirken "sigaction" yapısının "flags" parametresinin "SA_RESTART" biçiminde geçildiğine dikkat ediniz. Bu "recv" üzerinde beklerken oluşabilecek "SIGURG" sinyalinden sonra "recv" in otomatik yeniden başlatılması için kullanılmıştır. Yine buradaki "server" program port numarasını, "client" program ise "server" adresini ve port numarasını komut satırı argümanı olarak almaktadır. /* oobserver.c */ #include #include #include #include #include #include #include #include #include #define BUFFER_SIZE 1024 void sigurg_handler(int sno); void exit_sys(const char *msg); int sock_client; int main(int argc, char *argv[]) { int sock; struct sockaddr_in sinaddr, sinaddr_client; socklen_t sinaddr_len; char ntopbuf[INET_ADDRSTRLEN]; in_port_t port; ssize_t result; char buf[BUFFER_SIZE + 1]; struct sigaction sa; if (argc != 2) { fprintf(stderr, "wrong number of arguments!..\n"); exit(EXIT_FAILURE); } sa.sa_handler = sigurg_handler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); if (sigaction(SIGURG, &sa, NULL) == -1) exit_sys("sigaction"); port = (in_port_t)strtoul(argv[1], NULL, 10); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) exit_sys("socket"); sinaddr.sin_family = AF_INET; sinaddr.sin_port = htons(port); sinaddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock, (struct sockaddr *)&sinaddr, sizeof(sinaddr)) == -1) exit_sys("bind"); if (listen(sock, 8) == -1) exit_sys("listen"); printf("Waiting for connection...\n"); sinaddr_len = sizeof(sinaddr_client); if ((sock_client = accept(sock, (struct sockaddr *)&sinaddr_client, &sinaddr_len)) == -1) exit_sys("accept"); if (fcntl(sock_client, F_SETOWN, getpid()) == -1) exit_sys("fcntl"); printf("Connected: %s : %u\n", inet_ntop(AF_INET, &sinaddr_client, ntopbuf, INET_ADDRSTRLEN), (unsigned)ntohs(sinaddr_client.sin_port)); for (;;) { if ((result = recv(sock_client, buf, BUFFER_SIZE, 0)) == -1) exit_sys("recv"); if (result == 0) break; buf[result] = '\0'; if (!strcmp(buf, "quit")) break; printf("%ld bytes received from %s (%u): %s\n", (long)result, ntopbuf, (unsigned)ntohs(sinaddr_client.sin_port), buf); } shutdown(sock_client, SHUT_RDWR); close(sock_client); close(sock); return 0; } void sigurg_handler(int sno) { char oob; if (recv(sock_client, &oob, 1, MSG_OOB) == -1) exit_sys("recv"); printf("OOB Data received: %c\n", oob); } void exit_sys(const char *msg) { perror(msg); exit(EXIT_FAILURE); } /* oobclient.c */ #include #include #include #include #include #include #include #include #define BUFFER_SIZE 1024 void exit_sys(const char *msg); int main(int argc, char *argv[]) { int sock; struct addrinfo *ai, *ri; struct addrinfo hints = {0}; char buf[BUFFER_SIZE]; char *str; int result; if (argc != 3) { fprintf(stderr, "wrong number of arguments!..\n"); exit(EXIT_FAILURE); } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) exit_sys("socket"); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if ((result = getaddrinfo(argv[1], argv[2], &hints, &ai)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(result)); exit(EXIT_FAILURE); } for (ri = ai; ri != NULL; ri = ri->ai_next) if (connect(sock, ri->ai_addr, ri->ai_addrlen) != -1) break; if (ri == NULL) exit_sys("connect"); freeaddrinfo(ai); printf("Connected...\n"); for (;;) { printf("Yazı giriniz:"); if (fgets(buf, BUFFER_SIZE, stdin) == NULL) continue; if ((str = strchr(buf, '\n')) != NULL) *str = '\0'; if (!strcmp(buf, "quit")) break; if ((send(sock, buf, strlen(buf), buf[0] == 'u' ? MSG_OOB : 0)) == -1) exit_sys("send"); } shutdown(sock, SHUT_RDWR); close(sock); return 0; } void exit_sys(const char *msg) { perror(msg); exit(EXIT_FAILURE); }