আমি বিশ্বাস করি যে কোনও প্রোগ্রামে সকেটের অনুপলব্ধ ধারণাটি হ'ল ট্রানজিটে থাকা কোনও টিসিপি ডেটা বিভাগকে পৌঁছানোর অনুমতি দেওয়া এবং কার্নেল দ্বারা ফেলে দেওয়া। এটি হ'ল, কোনও অ্যাপ্লিকেশনটির জন্য close(2)
কোনও সকেটে কল করা সম্ভব , তবে প্যাকেটগুলি নিয়ন্ত্রণ করতে বিলম্ব বা দুর্ঘটনাগুলি ঘুরিয়ে দেওয়া বা আপনার কাছে টিসিপি সংযোগের অন্য দিকটি কিছুক্ষণের জন্য ডেটা প্রেরণের অনুমতি দিতে পারে। অ্যাপ্লিকেশনটি ইঙ্গিত করেছে যে এটি আর টিসিপি ডেটা বিভাগগুলির সাথে আর কোনও व्यवहार করতে চায় না, তাই কার্নেলটি কেবল তাদের আসার সাথে সাথে এগুলি ফেলে দেওয়া উচিত।
আমি সি তে একটি সামান্য প্রোগ্রাম হ্যাক করেছি যা আপনি সংকলন করতে এবং টাইমআউটটি কত দীর্ঘ তা দেখতে ব্যবহার করতে পারেন:
#include <stdio.h> /* fprintf() */
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <stdlib.h> /* strtol() */
#include <signal.h> /* signal() */
#include <sys/time.h> /* struct timeval */
#include <unistd.h> /* read(), write(), close(), gettimeofday() */
#include <sys/types.h> /* socket() */
#include <sys/socket.h> /* socket-related stuff */
#include <netinet/in.h>
#include <arpa/inet.h> /* inet_ntoa() */
float elapsed_time(struct timeval before, struct timeval after);
int
main(int ac, char **av)
{
int opt;
int listen_fd = -1;
unsigned short port = 0;
struct sockaddr_in serv_addr;
struct timeval before_bind;
struct timeval after_bind;
while (-1 != (opt = getopt(ac, av, "p:"))) {
switch (opt) {
case 'p':
port = (unsigned short)atoi(optarg);
break;
}
}
if (0 == port) {
fprintf(stderr, "Need a port to listen on\n");
return 2;
}
if (0 > (listen_fd = socket(AF_INET, SOCK_STREAM, 0))) {
fprintf(stderr, "Opening socket: %s\n", strerror(errno));
return 1;
}
memset(&serv_addr, '\0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
gettimeofday(&before_bind, NULL);
while (0 > bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
fprintf(stderr, "binding socket to port %d: %s\n",
ntohs(serv_addr.sin_port),
strerror(errno));
sleep(1);
}
gettimeofday(&after_bind, NULL);
printf("bind took %.5f seconds\n", elapsed_time(before_bind, after_bind));
printf("# Listening on port %d\n", ntohs(serv_addr.sin_port));
if (0 > listen(listen_fd, 100)) {
fprintf(stderr, "listen() on fd %d: %s\n",
listen_fd,
strerror(errno));
return 1;
}
{
struct sockaddr_in cli_addr;
struct timeval before;
int newfd;
socklen_t clilen;
clilen = sizeof(cli_addr);
if (0 > (newfd = accept(listen_fd, (struct sockaddr *)&cli_addr, &clilen))) {
fprintf(stderr, "accept() on fd %d: %s\n", listen_fd, strerror(errno));
exit(2);
}
gettimeofday(&before, NULL);
printf("At %ld.%06ld\tconnected to: %s\n",
before.tv_sec, before.tv_usec,
inet_ntoa(cli_addr.sin_addr)
);
fflush(stdout);
while (close(newfd) == EINTR) ;
}
if (0 > close(listen_fd))
fprintf(stderr, "Closing socket: %s\n", strerror(errno));
return 0;
}
float
elapsed_time(struct timeval before, struct timeval after)
{
float r = 0.0;
if (before.tv_usec > after.tv_usec) {
after.tv_usec += 1000000;
--after.tv_sec;
}
r = (float)(after.tv_sec - before.tv_sec)
+ (1.0E-6)*(float)(after.tv_usec - before.tv_usec);
return r;
}
আমি এই প্রোগ্রামটি 3 টি বিভিন্ন মেশিনে চেষ্টা করেছি এবং 55 থেকে 59 সেকেন্ডের মধ্যে যখন কার্নেল অ-রুট ব্যবহারকারীকে সকেটটি পুনরায় খোলার অনুমতি দিতে অস্বীকার করে তখন আমি একটি পরিবর্তনশীল সময় পাই। আমি উপরের কোডটি "ওপেনার" নামক একটি এক্সিকিউটেবলের কাছে সংকলিত করেছি এবং এটিকে এভাবে চালিয়েছি:
./opener -p 7896; ./opener -p 7896
আমি অন্য উইন্ডোটি খুললাম এবং এটি করেছি:
telnet otherhost 7896
এর ফলে "ওপেনার" এর প্রথম উদাহরণটি কোনও সংযোগ গ্রহণ করে, তারপরে এটি বন্ধ করে দেয়। "ওপেনার" এর দ্বিতীয় উদাহরণটি bind(2)
প্রতি সেকেন্ডে টিসিপি পোর্টে 7896 চেষ্টা করে। "ওপেনার" 55 থেকে 59 সেকেন্ড বিলম্বের কথা জানায়।
চারপাশে গুগল করে, আমি দেখতে পাচ্ছি যে লোকেরা এটি করার পরামর্শ দেয়:
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
যে অন্তর কমাতে। এটি আমার পক্ষে কাজ করে না। 4 টি লিনাক্স মেশিনে আমার অ্যাক্সেস ছিল, দুটিতে 30 এবং দুটিতে 60 টি ছিল I আমি সেই মানটি 10 হিসাবেও কম সেট করেছিলাম "" ওপেনার "প্রোগ্রামের সাথে কোনও পার্থক্য নেই।
এটা করছি:
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
জিনিস পরিবর্তন করেছেন। দ্বিতীয় "ওপেনার" এটির নতুন সকেট পেতে মাত্র 3 সেকেন্ড সময় নিয়েছিল।
man 2 bind
আপনি আমাকে বিশ্বাস না হলে চেষ্টা করুন । স্বীকার করা যায় যে, ইউনিক্স যখন কেউ "বাঁধাই" বলে যথেষ্ট পরিমাণে যথেষ্ট বলে এটি সম্ভবত প্রথম বিষয় নয়।