سی

توی بخش قبلی ما با پایتون تونستیم بنویسیم. حالا میخوایم این رو توی سی هم پیاده سازی کنیم.

اول ما چون میخوایم سوکت نویسی کنیم باید هدر های زیر رو اضافه کنیم:

sys/socket.h

arpa/inet.h

چون ما میخوایم چیزی رو توی صفحه نشون بدیم و اندازه رشته هارو بدونیم، سوکت رو ببندیم و ارور هارو هندل کنیم و ... باید چند تا هدر دیگه رو هم اضافه میکینم.

که با #include میتونید وارد کنید:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

حالا یه ماکرو میسازیم به اسم CONTROL_PORT که پورت خودمون رو بدیم.

#define CONTROL_PORT 8888

حالا باید تابع خودمون یا همون newnym رو declaration بکنیم:

void         newnym();

حالا میریم سراغ نوشتن تابعمون. اول باید تابع رو تعریف کنیم:

void
newnym()
{
}

حالا باید بیایم توصیف گر فایل سوکت رو تعریف کنیم (حتما میدونید دیگه توی یونیکس، با سوکت مثل فایل رفتار میشه)، یه متغیر از نوع عدد صحیح تعریف میکنیم که توصیف گر فایل رو توش ذخیره کنیم و یه پوینتر از نوع کارکتر تعریف میکنیم برای اینکه اون پیغام هایی که باید به تور بفرستیم رو توش ذخیره کنیم که تمیز تر باشه و با malloc یک کیلوبایت از حافظه dynamic رو بهش اختصاص میدیم:

int         sockfd;
char        *msg = (char *) malloc(1024);

حالا یه structure هم از نوع sockaddr_in تعریف میکنیم که بتونیم ایپی و پورت رو به سوکت بدیم:

struct sockaddr_in addr;

حالا برای اینکه مموری لیک رخ نده توی پوینتر msg و مطمئن شیم structure خالی هستش با memset خانه های حافظشون رو با 0 پر میکنیم:

memset(msg, 0x00, 1024);
memset(&addr, 0x00, sizeof(addr));

حالا نوبت تعریف کردن سوکت میرسه:

sockfd = socket(AF_INET , SOCK_STREAM , 0);

تابع سوکت یه توصیف گر فایل رو بر میگردونه. چون ما از ipv4 استفاده میکنیم از AF_INET و چون از TCP میخوایم استفاده کنیم از SOCK_STREAM استفاده میکنیم و اون 0 برای اینکه که مشخص کنیم ما از پروتکل IP میخوایم استفاده کنیم. اگه مقدار بازگشتی -1 باشه یعنی ساخت سوکت با خطا روبرو شد برای همین باید چک کنیم که -1 هست یا نه و اگه بود بیاد بیرون:

if (sockfd == -1) errx(EXIT_FAILURE, "Could not create socket.");

حالا باید ایپی و پورت رو توی structure مشخص کنیم:

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(0x7F000001); /* 127.0.0.1 */
addr.sin_port = htons(CONTROL_PORT); /* 8888 */

اول باید خانواده ایپی رو مشخص کنیم که ما ipv4 رو انتخاب کردیم

کار htonl اینه که عدد صحیح بدون علامت رو به byte order شبکه تبدیل میکنه برای همین ما ایپی رو به hex نوشتیم. کار سختی نیست. 127 میشه 7F و ما دو تا 0 داریم پس میشه 0000 و یه یک هم اخر داریم که میشه 01

نتیجه میشه 7F000001

و کار htons هم اینه که unsigned short integer hostshort رو به byte order شبکه تبدیل میکنه.

حالا بیایم کانکت شیم:

connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))

اگه عدد صحیح برگشتی منفی یک باشه یعنی خطا رخ داده برای همین ما مستقیم توی if استفادش میکنیم:

if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    errx(EXIT_FAILURE, "Connect failed.");

حالا وقت فرستادن دستوراته:

اول ما همون دستور احراز هویت رو توی msg ذخیره میکنیم و بعد ارسال میکنیم و این هم مثل connect اگه -1 باشه یعنی خطا رخ داده پس:

msg = "AUTHENTICATE \"1234567890\"\n";
if (send(sockfd, msg, strlen(msg), 0) == -1)
    errx(EXIT_FAILURE, "Send failed.");

و دستور سیگنال هم به همین صورت:

msg = "SIGNAL NEWNYM\n";
if (send(sockfd, msg, strlen(msg), 0) == -1)
    errx(EXIT_FAILURE, "Send failed.");

و حالا تموم شد و حالا باید سوکت رو ببندیم:

close(sockfd);

حالا باید تابع main رو تعریف کنیم و تابع newnym رو صدا بزنیم:

int
main(void)
{
    newnym();
    return 0;
}

کد نهایی:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define CONTROL_PORT 8888

void		 newnym();

void
newnym()
{
	int 		sockfd;
	char		*msg = (char *) malloc(1024);
	struct sockaddr_in addr;

	memset(msg, 0x00, 1024);
	memset(&addr, 0x00, sizeof(addr));

	
	sockfd = socket(AF_INET , SOCK_STREAM , 0);
	if (sockfd == -1) errx(EXIT_FAILURE, "Could not create socket.");
	
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(0x7F000001);
	addr.sin_port = htons(CONTROL_PORT);

	if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
		errx(EXIT_FAILURE, "Connect failed.");
	printf("Connected\n");
	
	msg = "AUTHENTICATE \"1234567890\"\n";
	if (send(sockfd, msg, strlen(msg), 0) == -1)
		errx(EXIT_FAILURE, "Send failed.");
	
	printf("%s", msg);
	
	msg = "SIGNAL NEWNYM\n";
	if (send(sockfd, msg, strlen(msg), 0) == -1)
		errx(EXIT_FAILURE, "Send failed.");
	
	printf("%s", msg);
	close(sockfd);
}

int
main(void)
{
	newnym();
	return 0;
}

Last updated