66send SMS messages, handle delivery receipts, and properly handle enhanced shutdown
77notifications from the server.
88
9- Enhanced Shutdown Features :
9+ Shutdown features :
1010- Receives and responds to server shutdown notifications
1111- Graceful disconnection when server requests shutdown
1212- Proper handling of connection loss during shutdown
1313- Interactive commands for testing shutdown scenarios
14-
15- Updated for the new modular code structure with clean imports from the main smpp package.
1614"""
1715
1816import asyncio
1917import logging
20- import os
21- import sys
2218from typing import Optional
2319
24- # Add parent directory to path for imports
25- sys .path .insert (0 , os .path .dirname (os .path .dirname (os .path .abspath (__file__ ))))
2620
2721from smpp import (
2822 BindType ,
4539
4640class SMSClient :
4741 """
48- Example SMS client using SMPP with enhanced shutdown handling .
42+ Example SMS client.
4943
5044 Features:
51- - Enhanced shutdown notification handling
45+ - Shutdown notification handling
5246 - Graceful disconnection on server shutdown
5347 - Interactive command support
54- - Proper connection lifecycle management
5548 """
5649
5750 def __init__ (self , host : str , port : int , system_id : str , password : str ):
@@ -60,12 +53,12 @@ def __init__(self, host: str, port: int, system_id: str, password: str):
6053 port = port ,
6154 system_id = system_id ,
6255 password = password ,
63- system_type = 'CLIENT' , # Fixed: SMPP system_type must be <= 13 characters
56+ system_type = 'CLIENT' , # SMPP system_type must be <= 13 characters
6457 enquire_link_interval = 30.0 ,
6558 response_timeout = 10.0 ,
6659 )
6760
68- # Enhanced shutdown handling with thread safety
61+ # Shutdown handling with thread safety
6962 self ._shutdown_lock = asyncio .Lock ()
7063 self ._shutdown_state = 'running' # running, shutting_down, stopped
7164 self ._shutdown_grace_period = 0
@@ -87,7 +80,7 @@ def handle_deliver_sm(self, client: SMPPClient, pdu: DeliverSm) -> None:
8780 if pdu .esm_class & 0x04 : # Delivery receipt
8881 logger .info ('📧 Delivery receipt received:' )
8982 logger .info (f' From: { pdu .source_addr } → To: { pdu .destination_addr } ' )
90- logger .info (f' Receipt: { message } ' )
83+ logger .debug (f' Receipt: { message } ' )
9184
9285 # Check for shutdown notifications from the server
9386 elif self ._is_shutdown_notification (pdu , message ):
@@ -169,7 +162,9 @@ def _handle_shutdown_notification(self, pdu: DeliverSm, message: str) -> None:
169162 # Start graceful shutdown process
170163 asyncio .create_task (self ._initiate_graceful_shutdown ())
171164
172- async def _initiate_graceful_shutdown (self , urgent : bool = False ) -> None :
165+ async def _initiate_graceful_shutdown (
166+ self , urgent : bool = False , default_delay : float = 0.5
167+ ) -> None :
173168 """Thread-safe graceful shutdown process."""
174169 async with self ._shutdown_lock :
175170 if self ._shutdown_state != 'running' :
@@ -187,7 +182,7 @@ async def _initiate_graceful_shutdown(self, urgent: bool = False) -> None:
187182 # Use a fraction of the server's grace period, but cap it reasonably
188183 delay = min (max (0.1 , self ._shutdown_grace_period * 0.5 ), 2.0 )
189184 else :
190- delay = 0.5 # Default to 0.5s instead of 3.0s for faster tests
185+ delay = default_delay # Default to 0.5s instead of 3.0s for faster tests
191186 logger .info (f'⏱️ Graceful shutdown in { delay :.1f} seconds...' )
192187
193188 await asyncio .sleep (delay )
@@ -390,12 +385,12 @@ async def main():
390385 - Connecting and binding to SMSC
391386 - Sending various types of messages
392387 - Interactive command support
393- - Enhanced shutdown notification handling
388+ - Shutdown notification handling
394389 - Graceful disconnection
395390 """
396391 # SMSC connection details - compatible with SMPP protocol (max 8 chars for password)
397392 SMSC_HOST = 'localhost'
398- SMSC_PORT = 9999 # Changed to high port number
393+ SMSC_PORT = 2775 # Changed to high port number
399394 SYSTEM_ID = 'test_client'
400395 PASSWORD = 'password' # Fixed: SMPP passwords must be <= 8 characters
401396
@@ -404,10 +399,6 @@ async def main():
404399
405400 try :
406401 logger .info ('🚀 Enhanced SMPP Client starting...' )
407- logger .info (
408- '🔧 Features: Shutdown notification handling, graceful disconnection'
409- )
410- logger .info ('' )
411402
412403 # Connect and bind as transceiver (can send and receive)
413404 await sms_client .connect_and_bind (BindType .TRANSCEIVER )
@@ -439,7 +430,7 @@ async def main():
439430 await sms_client .send_unicode_sms (
440431 source_addr = '12345' ,
441432 destination_addr = '67890' ,
442- message = 'Unicode test: Hello 世界! 🌍 Enhanced shutdown ready!' ,
433+ message = 'Unicode test: Hello 世界! 🌍 Shutdown ready!' ,
443434 request_delivery_receipt = True ,
444435 )
445436
@@ -525,7 +516,7 @@ async def simple_send_example():
525516
526517 async with SMPPClient (
527518 host = 'localhost' ,
528- port = 9999 , # Changed to high port number
519+ port = 2775 , # Changed to high port number
529520 system_id = 'test_client' ,
530521 password = 'password' , # Fixed: SMPP passwords must be <= 8 characters
531522 ) as client :
@@ -553,7 +544,7 @@ async def monitor_messages_example():
553544
554545 client = SMPPClient (
555546 host = 'localhost' ,
556- port = 9999 , # Changed to high port number
547+ port = 2775 , # Changed to high port number
557548 system_id = 'test_receiver' ,
558549 password = 'password' , # Fixed: SMPP passwords must be <= 8 characters
559550 )
@@ -608,7 +599,7 @@ async def interactive_client_example():
608599
609600 # Create enhanced client
610601 sms_client = SMSClient (
611- 'localhost' , 9999 , 'demo_client' , 'demo_pas'
602+ 'localhost' , 2775 , 'demo_client' , 'demo_pas'
612603 ) # Changed to high port number
613604
614605 try :
0 commit comments