
در دنیای امروزی که ارتباطات نرمافزارها از طریق شبکه حرف اول را میزند، اوراکل هم برای توسعهدهندگانی که به ارتباطات سطح پایین نیاز دارند، ابزار قدرتمندی در اختیار گذاشته:
پکیجی به نام UTL_TCP.
با استفاده از این پکیج میتوانی از درون دیتابیس مستقیماً با هر سرویس TCP ارتباط بگیری؛
چه یک سرور داخلی لاگین، دستگاه صنعتی IoT یا حتی یک ماژول حسابداری بیمهای که پیام JSON دریافت میکند — همه از طریق PL/SQL!
در این مقاله آموزش Oracle در بخش آموزش پکیج های اوراکلی در مورد پکیج UTL_TCP صبحت کنیم.
اگر با پایگاه داده اوراکل کار کرده باشی، حتماً اسم Materialized View به گوشت خورده. این ساختار، در واقع یک جدول ذخیرهشده از نتایج یک Query است که میتونه به صورت دورهای یا دستی آپدیت بشه. پیشنهاد می کنم این مقاله زیر رو حتما مطالعه کنی.
در این مقاله شما می خوانید
🚀 پکیج UTL_TCP چیست و چه کاری انجام میدهد؟
به زبان ساده، UTL_TCP در Oracle Database مثل یک کلاینت TCP کوچک درون دیتابیس است.
این پکیج اجازه میدهد با استفاده از PL/SQL:
- به هر سرور TCP/IP متصل شوی
- داده ارسال کنی
- پاسخ دریافت کنی
- جریان داده را بهصورت متنی یا باینری کنترل کنی
در واقع همان کاری که در زبانهایی مثل Python یا #C با Socket انجام میدهی، در اوراکل با UTL_TCP هم شدنی است.
⚙️ ساختار و توابع کلیدی پکیج UTL_TCP
برای استفاده حرفهای از UTL_TCP، باید توابع و قابلیتهای اصلی آن را بشناسی. در ادامه همهی موارد مهم را توضیح دادهام همراه با کاربردهای واقعی هرکدام:
| تابع / پروسیجر | توضیح عملکرد | نکات مهم |
|---|---|---|
| UTL_TCP.OPEN_CONNECTION | ایجاد اتصال با هاست و پورت مشخص | لازم است قبل از هر ارسال داده فراخوانی شود. |
| UTL_TCP.CLOSE_CONNECTION | بستن ارتباط باز | همیشه در بلوک Exception هم بنویس تا اتصال در هر شرایطی بسته شود. |
| UTL_TCP.WRITE_LINE | ارسال رشته متنی با CR/LF در انتها | مناسب برای سرویسهایی که پاسخ خطی میدهند. |
| UTL_TCP.WRITE_RAW | ارسال داده باینری RAW | کاربرد در Stream یا فایل Base64. |
| UTL_TCP.GET_LINE | خواندن پاسخ تا رسیدن به خط جدید | اگر TRUE بدهی، کاراکترهای انتهایی حذف میشوند. |
| UTL_TCP.READ_RAW | دریافت داده باینری با طول مشخص | برای فایل، تصویر یا جریان بزرگ داده (LOB) کاربرد دارد. |
| UTL_TCP.FLUSH | ارسال فوری دادههای بافر | بدون آن داده ممکن است ارسال نشود. |
| UTL_TCP.END_OF_INPUT | اکسپشن اختصاصی برای پایان ورودی | برای کنترل حلقه دریافت پاسخ ضروری است. |
🧭 تنظیمات امنیتی: ACL یا مجوز دسترسی شبکه
از نسخه ۱۱g، اوراکل دسترسی به شبکه را محدود کرده است.
اگر ACL ست نشده باشد، با خطای معروف ORA-24247 روبهرو میشوی.
برای فعالسازی دسترسی TCP، باید با DBMS_NETWORK_ACL_ADMIN مجوز صادر کنی:
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl(
acl => 'utl_tcp_acl.xml',
description => 'Allow UTL_TCP networking for HR',
principal => 'HR',
is_grant => TRUE,
privilege => 'connect'
);
DBMS_NETWORK_ACL_ADMIN.assign_acl(
acl => 'utl_tcp_acl.xml',
host => 'example.com',
lower_port => ۸۰۰۰,
upper_port => ۸۰۰۰
);
COMMIT;
END;
/
بعد از اجرای این بلاک، کاربر HR اجازه دارد از پکیج UTL_TCP برای اتصال به میزبان مشخصشده استفاده کند.
💬 مثالی از ارتباط با سرویس TCP با پکیج UTL_TCP
DECLARE
l_conn UTL_TCP.connection;
l_line VARCHAR2(32767);
BEGIN
l_conn := UTL_TCP.open_connection('example.com', 8080, charset => 'UTF8');
UTL_TCP.write_line(l_conn, 'HELLO FROM ORACLE');
UTL_TCP.flush(l_conn);
LOOP
BEGIN
l_line := UTL_TCP.get_line(l_conn, TRUE);
DBMS_OUTPUT.put_line('Server response: ' || l_line);
EXCEPTION
WHEN UTL_TCP.end_of_input THEN EXIT;
END;
END LOOP;
UTL_TCP.close_connection(l_conn);
END;
/
✅ اجرای صحیح، مشروط به تنظیم ACL و باز بودن پورت ۸۰۸۰ در سرور مقصد است.
💡 سناریوی واقعی: ارتباط با سیستم داخلی بیمه با پکیج UTL_TCP
در پروژههای بیمهای، سیستمهای داخلی اغلب روی پورت خاصی منتظر دریافت پیام TCP هستند.
کد زیر ارتباط با چنین سیستمی را از درون دیتابیس نشان میدهد:
DECLARE
l_conn UTL_TCP.connection;
l_req VARCHAR2(32767);
l_resp VARCHAR2(32767);
BEGIN
l_req := '{"transaction":"POLICY_INQUIRY","policy_no":"A89011"}';
l_conn := UTL_TCP.open_connection('192.168.10.15', 9100, charset => 'UTF8');
UTL_TCP.write_line(l_conn, l_req);
UTL_TCP.flush(l_conn);
LOOP
BEGIN
l_resp := UTL_TCP.get_line(l_conn, TRUE);
DBMS_OUTPUT.put_line('Response: ' || l_resp);
EXCEPTION
WHEN UTL_TCP.end_of_input THEN EXIT;
END;
END LOOP;
UTL_TCP.close_connection(l_conn);
END;
/
نتیجه معمولاً پاسخ JSON از سمت سیستم بیمه است که میتوان با JSON_VALUE() یا JSON_TABLE() پردازش کرد.
🧱 مثالی پیشرفتهتر: دریافت داده باینری از سرور با پکیج UTL_TCP
DECLARE
l_conn UTL_TCP.connection;
l_chunk RAW(32767);
BEGIN
l_conn := UTL_TCP.open_connection('192.168.1.70', 7070);
UTL_TCP.write_raw(l_conn, UTL_RAW.cast_to_raw('GET_FILE'));
UTL_TCP.flush(l_conn);
LOOP
BEGIN
l_chunk := UTL_TCP.read_raw(l_conn, 1024);
DBMS_OUTPUT.put_line('Received chunk: ' || RAWTOHEX(l_chunk));
EXCEPTION
WHEN UTL_TCP.end_of_input THEN EXIT;
END;
END LOOP;
UTL_TCP.close_connection(l_conn);
END;
/
🟢 این روش معمولاً برای مانیتورینگ سیستمها، ارسال فایل بین سرویسها و ارتباط با سختافزار کاربرد دارد.
⚡ نکات حرفهای برای بهینهسازی عملکرد پکیج UTL_TCP
- Buffer Size را متناسب با حجم داده تعیین کن (پیشفرض ۸۱۹۲ بایت است).
- از
tx_timeoutدرOPEN_CONNECTIONاستفاده کن تا فرآیند قفل نشود. - حتماً
flushرا پس از هر send بنویس. - charset را
AL32UTF8تنظیم کن تا خطای کاراکتری نگیری. - connection را همیشه در Exception block ببند تا نشت ارتباط رخ ندهد.
🚨 خطاهای متداول و راهکارها در پکیج UTL_TCP
| کد خطا | علت | راهحل |
|---|---|---|
| ORA-24247 | مجوز ACL وجود ندارد | تعریف ACL با DBMS_NETWORK_ACL_ADMIN |
| ORA-29260 | خطای شبکه یا بسته برگشتی | بررسی فایروال، DNS و پورت |
| ORA-29263 | Timeout در خواندن داده | افزودن tx_timeout یا بررسی latency شبکه |
| ORA-06502 | خطای تبدیل کاراکتر یا نوع داده | تنظیم charset در open_connection به 'AL32UTF8' |
🌍 کاربردهای واقعی پکیج UTL_TCP
پکیج UTL_TCP فقط برای آزمایش شبکه نیست؛ بلکه در پروژههای حرفهای استفاده میشود:
- ارتباط دیتابیس با سرورهای Log و QueueWriter داخلی
- ارتباط سیستمهای بیمه، مالی یا ERP سفارشی از طریق سوکت
- ارسال داده به تجهیزات صنعتی (PLC / IoT)
- اجرای handshake بین دیتابیسهای جداگانه
- ساخت ابزار مانیتورینگ و پینگ TCP در PL/SQL
سوالات متداول درباره پکیج UTL_TCP در اوراکل
پکیج UTL_TCP در دیتابیس اوراکل ابزاری برای ایجاد اتصال مستقیم TCP/IP از درون PL/SQL است.
به کمک آن میتوانی داده را از داخل سرور دیتابیس به سرویسهای خارجی بفرستی یا از آنها پاسخ بگیری.
این پکیج مثل یک Socket Client داخلی عمل میکند و معمولاً برای ارتباط با سرویسهای داخلی سازمان، دستگاهها، یا سرورهای سفارشی استفاده میشود.
UTL_HTTP برای برقراری ارتباط با سرویسهای وب (HTTP / HTTPS) طراحی شده، مثل REST API یا وبسرویسها.
اما UTL_TCP در سطح پایینتر کار میکند؛ یعنی فقط با پروتکل TCP خام سر و کار دارد و برای سناریوهایی که ساختار پروتکل خاصی ندارند (مثل ارتباط با یک سوکت سفارشی یا سرور لاگ TCP) ایدهآل است.
به زبان ساده:
🔹 اگر سرویس مقصد URL و header دارد ⇒
UTL_HTTP🔹 اگر فقط IP و Port دارد ⇒
UTL_TCP
این خطا یکی از شایعترین خطاهای هنگام استفاده از UTL_TCP است.
علتش این است که از اوراکل ۱۱g به بعد، همه ارتباطات شبکهای نیاز به مجوز (ACL) دارند.
برای رفع آن باید با بستهی DBMS_NETWORK_ACL_ADMIN یک ACL بسازی و کاربر را داخل آن اضافه کنی، مثلاً:
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl( acl => ‘utl_tcp_acl.xml’, principal => ‘HR’, is_grant => TRUE, privilege => ‘connect’);
DBMS_NETWORK_ACL_ADMIN.assign_acl( acl => ‘utl_tcp_acl.xml’, host => ‘example.com’, lower_port => ۸۰۸۰);
COMMIT;
END; /
بعد از اجرای این کد، مشکل دسترسی شبکه حل میشود.
برای ارسال JSON به سرویس TCP داخلی، کافی است با UTL_TCP.OPEN_CONNECTION اتصال برقرار کرده و سپس داده را با WRITE_LINE بفرستی؛ مثلاً:
DECLARE
conn UTL_TCP.connection;
BEGIN
conn := UTL_TCP.open_connection(‘۱۹۲.۱۶۸.۱۰.۱۵’, ۹۱۰۰, charset => ‘UTF8’);
UTL_TCP.write_line(conn, ‘{“type”:”PING”}’); UTL_TCP.flush(conn);
DBMS_OUTPUT.put_line(UTL_TCP.get_line(conn, TRUE));
UTL_TCP.close_connection(conn);
END;
این روش در سازمانهایی مثل بیمه و بانکی که سرویسهای TCP داخلی دارند بسیار پرکاربرد است و با ACL فعال بهخوبی کار میکند.
جمعبندی
پکیج UTL_TCP یکی از انعطافپذیرترین بخشهای اوراکل است.
اگر نیاز به ارتباط مستقیم TCP از درون PL/SQL داری، این ابزار دقیقاً همان چیزی است که باید یاد بگیری.
با این حال، چون دسترسی سطح پایین به شبکه دارد، امنیت (ACL) و مدیریت استثناها حیاتی است.
بهصورت خلاصه:
🔹 برای ارتباط سفارشی و سرویسهای خاص از
UTL_TCP🔹 برای APIهای HTTP از
UTL_HTTP🔹 و برای ارسال ایمیل از
UTL_SMTPاستفاده کن.
📥 اگر سوالی داری در مورد پکیج UTL_TCP در اوراکل داری، در بخش کامنتها بپرس.

دیدگاهتان را بنویسید