{"id":926,"date":"2026-01-11T20:57:21","date_gmt":"2026-01-11T11:57:21","guid":{"rendered":"https:\/\/team-okada.com\/?p=926"},"modified":"2026-01-11T20:57:21","modified_gmt":"2026-01-11T11:57:21","slug":"python%e3%81%a7sip%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%a8%e9%80%81%e5%8f%97%e4%bf%a1","status":"publish","type":"post","link":"https:\/\/team-okada.com\/?p=926","title":{"rendered":"Python\u3067SIP\u30b5\u30fc\u30d0\u30fc\u3068\u9001\u53d7\u4fe1"},"content":{"rendered":"\n<p>Python\u306esocket\u3092\u4f7f\u7528\u3057\u3066UDP\u901a\u4fe1\u3067SIP\u30b5\u30fc\u30d0\u30fc\u306bREGISTER \u30ea\u30af\u30a8\u30b9\u30c8\u3092\u884c\u3044\u3001IP \u30a2\u30c9\u30ec\u30b9\u3092&nbsp;SIP\u30b5\u30fc\u30d0\u30fc\u306b\u767b\u9332\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>IP\u96fb\u8a71\u304cUDP\u30d7\u30ed\u30c8\u30b3\u30eb\u3092\u4f7f\u7528\u3059\u308b\u7406\u7531<\/strong><br>\u3000UDP (User Datagram Protocol) \u306f\u3001\u30c7\u30fc\u30bf\u3092\u9001\u308b\u3060\u3051\u306e\u30b7\u30f3\u30d7\u30eb\u306a\u30d7\u30ed\u30c8\u30b3\u30eb\u3067\u3059\u3002\u4ed6\u306e\u30d7\u30ed\u30c8\u30b3\u30eb\u306b\u6bd4\u3079\u3066\u30c7\u30fc\u30bf\u304c\u6b63\u3057\u304f\u5c4a\u3044\u305f\u304b\u3092\u78ba\u8a8d\u3059\u308b\u4ed5\u7d44\u307f\u3092\u7701\u7565\u3057\u3001\u4fe1\u983c\u6027\u3084\u78ba\u5b9f\u6027\u3088\u308a\u3082\u901f\u5ea6(\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u6027)\u3092\u91cd\u8996\u306e\u52d5\u753b\u3084\u97f3\u58f0\u306e\u30b9\u30c8\u30ea\u30fc\u30df\u30f3\u30b0\u3001\u30aa\u30f3\u30e9\u30a4\u30f3\u30b2\u30fc\u30e0\u306a\u3069\u306b\u4f7f\u7528\u3055\u308c\u308b\u30d7\u30ed\u30c8\u30b3\u30eb\u3067\u3059\u3002UDP\u901a\u4fe1\u30d7\u30ed\u30c8\u30b3\u30eb\u306fIP\u96fb\u8a71\u306b\u9069\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>Python\u306esocket()\u95a2\u6570\u3092\u4f7f\u7528\u3057\u305fUDP\u306e\u901a\u4fe1\u306e\u6d41\u308c\u306f\u4ee5\u4e0b\u306e\u3068\u304a\u308a\u3067\u3059\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><font size=\"3\">\u30b5\u30fc\u30d0\u30fc(SIP\u30b5\u30fc\u30d0\u30fc)    \u30af\u30e9\u30a4\u30a2\u30f3\u30c8(IP\u96fb\u8a71)<\/font>\n<font size=\"2\">\u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">socket()<\/mark>\u3011                \u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">socket()<\/mark>\u3011   <mark style=\"background-color:rgba(0, 0, 0, 0);color:#00ff00\" class=\"has-inline-color\">\u30bd\u30b1\u30c3\u30c8\u3092\u4f5c\u6210\u3059\u308b<\/mark>\n   \u2193                           \u2193\n\u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">bind()<\/mark>\u3011                                <mark style=\"background-color:rgba(0, 0, 0, 0);color:#00ff00\" class=\"has-inline-color\">\u5f85\u53d7\u3051IP\u30a2\u30c9\u30ec\u30b9\u3068\u30dd\u30fc\u30c8\u756a\u53f7\u3092\u8a2d\u5b9a\u3059\u308b<\/mark>\n   \u2193\n\u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">recvfrom()<\/mark>\u3011  <em><mark style=\"background-color:rgba(0, 0, 0, 0);color:#ff0000\" class=\"has-inline-color\">&lt;-- \u30c7\u30fc\u30bf<\/mark> <\/em>  \u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">sendto()<\/mark>\u3011   <mark style=\"background-color:rgba(0, 0, 0, 0);color:#00ff00\" class=\"has-inline-color\">\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u30b5\u30fc\u30d0\u30fc\u306b\u9001\u4fe1\u3059\u308b<\/mark>\n   \u2193                           \u2193\n\u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">sendto()<\/mark>\u3011    <mark style=\"background-color:rgba(0, 0, 0, 0);color:#ff0000\" class=\"has-inline-color\"><em>\u30c7\u30fc\u30bf --&gt;<\/em><\/mark>   \u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">recv()<\/mark>\u3011     <mark style=\"background-color:rgba(0, 0, 0, 0);color:#00ff00\" class=\"has-inline-color\">\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306b\u9001\u4fe1\u3059\u308b<\/mark>\n   \u2193                           \u2193\n\u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">close()<\/mark>\u3011                 \u3010<mark style=\"background-color:rgba(0, 0, 0, 0);color:#0000ff\" class=\"has-inline-color\">close()<\/mark>\u3011    <mark style=\"background-color:rgba(0, 0, 0, 0);color:#00ff00\" class=\"has-inline-color\">\u30bd\u30b1\u30c3\u30c8\u3092\u9589\u3058\u308b<\/mark><\/font><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8(IP\u96fb\u8a71)\u5074\u306eUDP\u3092\u4f7f\u3063\u305f\u7c21\u5358\u306a\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0<\/strong><\/p>\n\n\n\n<p>udp_client.py<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-base-color has-contrast-background-color has-text-color has-background has-link-color has-small-font-size\" style=padding-top:var(--wp--preset--spacing--20);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20);\"><copy>#!\/usr\/bin\/python3\n\nimport socket\n\nHOST = \"192.168.0.201\"\nPORT = 5060\n\n# \u9001\u4fe1\u6587\u5b57\u5217(\u30bd\u30d5\u30c8\u30d5\u30a9\u30f3\u8d77\u52d5\u6642\u306bSIP\u30b5\u30fc\u30d0\u30fc\u306b\u9001\u4fe1\u3057\u305f\u5185\u5bb9\u3092Wireshark\u3067\u5165\u624b)\nMESSAGE = '''REGISTER sip:192.168.0.201 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nMax-Forwards: 70\nContact: &lt;sip:20@192.168.0.41&gt;\nTo: &lt;sip:20@192.168.0.201&gt;\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=b50e84ed\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nCSeq: 1 REGISTER\nExpires: 3600\nContent-Length: 0'''\n\n# \u30bd\u30b1\u30c3\u30c8\u4f5c\u6210\nsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n\n# \u30e1\u30c3\u30bb\u30fc\u30b8\u9001\u4fe1\nsock.sendto(MESSAGE.encode('utf-8'), (HOST, PORT))\nprint('Sent message >>>>>')\nprint('====================')\nprint(MESSAGE)\nprint('====================')\n\n# \u30e1\u30c3\u30bb\u30fc\u30b8\u53d7\u4fe1\nrecv_message = sock.recv(1024)\n\nprint(f'Received message >>>>>')\nprint('====================')\nprint(recv_message.decode('utf-8'))\nprint('====================')\n\n# \u30bd\u30b1\u30c3\u30c8\u3092\u9589\u3058\u308b\nsock.close()<\/copy><\/pre>\n\n\n\n<p>udp_client.py\u306e\u5b9f\u884c\u7d50\u679c(Asterisk\u8d77\u52d5\u3057\u3066\u3044\u308b\u524d\u63d0)<\/p>\n\n\n\n<pre style=\"line-height: 12px;font-size: 12px; background: #eeeeee; overflow-x: scroll;overflow-y: hidden; padding: 10px 0 10px 1em;\">Sent message &gt;&gt;&gt;&gt;&gt;\n====================\nREGISTER sip:192.168.0.201 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nMax-Forwards: 70\nContact: &lt;sip:20@192.168.0.41&gt;\nTo: &lt;sip:20@192.168.0.201&gt;\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=b50e84ed\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nCSeq: 1 REGISTER\nExpires: 3600\nContent-Length: 0\n====================\nReceived message &gt;&gt;&gt;&gt;&gt;\n====================\nSIP\/2.0 401 Unauthorized\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;rport=58482;received=192.168.0.201;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=b50e84ed\nTo: &lt;sip:20@192.168.0.201&gt;;tag=z9hG4cK6b86b273ff34fce19d6b804ef\nCSeq: 1 REGISTER\nWWW-Authenticate: Digest realm=\"asterisk\",nonce=\"1763994373\/8074807feebaac3410e79cb9f9586de0\",opaque=\"0f8adef278a327a1\",algorithm=MD5,qop=\"auth\"\nServer: Asterisk PBX 23.0.0\nContent-Length:  0\n\n\n====================\n<br><\/font><\/pre>\n\n\n\n<p>SIP\u30b5\u30fc\u30d0\u30fc\u3068\u30af\u30e9\u30a4\u30a2\u30f3\u30c8PC\u306e\u30b7\u30fc\u30b1\u30f3\u30b9<\/p>\n\n\n\n<pre style=\"line-height: 15px;font-size: 15px; background: #eeeeee; padding: 10px 0 10px 1em;\">      \u5185\u7dda20                         SIP\u30b5\u30fc\u30d0\u30fc\n      IP:192.168.0.41                IP:192.168.0.201\n\n         |                              |\n         |(1) REGISTER                  |\n         |-----------------------------&gt;|\n         |(2) 401 Unauthorized          |\n         |&lt;-----------------------------|\n         |                              |\n<\/pre>\n\n\n\n<p>SIP\u30b5\u30fc\u30d0\u30fc\u3078\u306eUDP 5060\u756a\u30dd\u30fc\u30c8\u3067\u300cREGISTER\u300d\u3092\u9001\u4fe1\u3059\u308b\u3068SIP\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u300c401 Unauthorized\u300d\u304c\u8fd4\u4fe1\u3055\u308c\u308b\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>SIP\u30b5\u30fc\u30d0\u30fc\u306b\u5185\u7dda20\u3092\u767b\u9332\u3057\u3066\u7740\u4fe1\u53ef\u80fd\u306b\u3059\u308b\u30b3\u30fc\u30c9\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/strong><\/p>\n\n\n\n<p>\u8a2d\u5b9a\u5185\u5bb9<br>\u3000SIP\u30b5\u30fc\u30d0\u30fcIP:\u300c192.168.0.201\u300d<br>\u3000\u30dd\u30fc\u30c8:\u300c5060\u300d<\/p>\n\n\n\n<p>\u3000\u30bd\u30d5\u30c8\u30d5\u30a9\u30f3ID:\u300c21\u300d<\/p>\n\n\n\n<p>\u3000\u81ea\u5206IP:\u300c192.168.0.41\u300d<br>\u3000\u81ea\u5206ID:\u300c20\u300d<br>\u3000\u30d1\u30b9\u30ef\u30fc\u30c9:\u300cpass\u300d<\/p>\n\n\n\n<p>sip_client.py<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-base-color has-contrast-background-color has-text-color has-background has-link-color has-small-font-size\" style=padding-top:var(--wp--preset--spacing--20);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20);\"><copy>#!\/usr\/bin\/python3\n\nimport socket\nimport sys\nimport re\nimport signal\nimport random\nimport hashlib\n\nSERVER_IP = '192.168.0.201' #SIP\u30b5\u30fc\u30d0\u30fc\u30a2\u30c9\u30ec\u30b9\nMY_IP = '192.168.0.41' #\u81ea\u5206\u306eIP\u30a2\u30c9\u30ec\u30b9\n\nPORT = 5060 \n\nID = '20' #ID\nPASS = 'pass' #\u30d1\u30b9\u30ef\u30fc\u30c9\n\nclass Counter():\n  def __init__(self, start=1):\n    self.i = start\n    \n  def next(self):\n    i = self.i\n    self.i += 1\n    return i\n\nclass SIP_message():\n  def __init__(self, data):\n    self.status = 0\n    self.headers = {}\n    self.parse(data)\n\n  def parse(self, data):\n    headers = data.split(b'\\r\\n\\r\\n')[0]\n    header = headers.split(b'\\r\\n')\n    \n    if str(header[0].split(b\" \")[0], 'utf8') in ['SIP\/2.0']:\n      self.version = str(header[0].split(b\" \")[0], 'utf8') \n      self.status = int(header[0].split(b\" \")[1])\n      \n    elif str(header[0].split(b\" \")[0], 'utf8') in ['INVITE', 'ACK', 'BYE', 'CANCEL']:\n      self.version = str(header[0].split(b\" \")[2], 'utf8')\n      self.method = str(header[0].split(b\" \")[0], 'utf8')\n\n    headers = {}\n        \n    for x in header[1:]:\n      row = str(x, 'utf8').split(': ')\n      headers[row[0]] = row[1]\n      \n    for x in headers:\n      self.parseHeader(x, headers[x])\n\n  def parseHeader(self, header, data):\n    if header==\"Via\":\n      split_data = re.split(\" |;\", data)\n      self.headers['Via'] = {'type': split_data[0], 'address': split_data[1]}\n      for x in split_data[2:]: \n        if '=' in x:\n          self.headers['Via'][x.split('=')[0]] = x.split('=')[1]\n        else:\n          self.headers['Via'][x] = None\n    elif header==\"From\" or header==\"To\":\n      split_data = data.split(';tag=')\n      tag = ''\n      if len(split_data) >= 2:\n        tag = split_data[1]\n      sip_url = split_data[0]\n      \n      self.headers[header] = {'sip_url': sip_url, 'tag': tag}\n    elif header==\"CSeq\":\n      self.headers[header] = {'check': data.split(\" \")[0], 'method': data.split(\" \")[1]}\n    elif header==\"Allow\" or header==\"Supported\":\n      self.headers[header] = data.split(\", \")\n    elif header==\"Content-Length\":\n      self.headers[header] = int(data)\n    elif header=='WWW-Authenticate':\n      data = data.replace(\"Digest\", \"\")\n      split_data = data.split(\",\")\n      header_data = {}\n      for x in split_data:\n        x = x.strip()\n        header_data[x.split('=')[0]] = x.split('=')[1].strip('\"')\n      self.headers[header] = header_data\n    else:\n      self.headers[header] = data\n\nclass SIP_connect():\n    def __init__(self, server, port, username, password, myIP):\n        self.server = server\n        self.port = port\n        self.myIP = myIP\n        self.username = username\n        self.password = password\n        self.tags = []\n        self.tagLibrary = {}\n        self.registerCounter = Counter()\n        self.callID = Counter()\n        \n    def genCallID(self):\n        return hashlib.sha256(str(self.callID.next()).encode('utf8')).hexdigest()[0:32]+\"@\"+self.myIP+\":\"+str(self.port)\n    \n    def Tag(self):\n        while True:\n            tag = hashlib.md5(str(random.randint(1, 4294967296)).encode('utf8')).hexdigest()[0:8]\n            if tag not in self.tags:\n                self.tags.append(tag)\n                return tag\n\n    def Authorization(self, response):\n        HA1 = hashlib.md5(self.username.encode('utf8')+b':'+response.headers['WWW-Authenticate']['realm'].encode('utf8')+b':'+self.password.encode('utf8')).hexdigest().encode('utf8')\n        HA2 = hashlib.md5(response.headers['CSeq']['method'].encode('utf8')+b':sip:'+self.server.encode('utf8')).hexdigest().encode('utf8')\n        nonce = response.headers['WWW-Authenticate']['nonce'].encode('utf8')\n        result = hashlib.md5(HA1+b':'+nonce+b':'+HA2).hexdigest().encode('utf8')\n   \n        return result\n        \n    def Register(self, response): \n        if response == '':\n            branch = \"z9hG4cK\"+self.genCallID()[0:25]\n            call_id = self.genCallID()\n        else:\n            result = self.Authorization(response)\n            branch = response.headers['Via']['branch']\n            call_id = response.headers['Call-ID']\n            nonce = response.headers['WWW-Authenticate']['nonce']\n            realm = response.headers['WWW-Authenticate']['realm']\n        \n        message = \"REGISTER sip:\"+self.server\n        message += \" SIP\/2.0\\r\\nVia: SIP\/2.0\/UDP \"+self.myIP+\":\"+str(self.port)+\";branch=\"+branch\n        message += \"\\r\\nMax-Forwards: 70\\r\\nContact: <sip:\"\n        message += self.username+\"@\"+self.myIP\n        message += \">\\r\\nTo: <sip:\"\"\"+self.username+\"@\"\n        message += self.server+\">\\r\\nFrom: <sip:\"+self.username\n        message += \"@\"+self.server+\">;tag=\"+self.Tag()\n        message += \"\\r\\nCall-ID: \"+call_id\n        message += \"\\r\\nCSeq: \"+str(self.registerCounter.next())+\" REGISTER\"\n        message += \"\\r\\nExpires: 3600\\r\\n\"\n\n        if response != '':\n            message += 'Authorization: Digest username=\"'+self.username\n            message += '\",realm=\"'+realm+'\",nonce=\"'+nonce\n            message += '\",uri=\"sip:'+self.server\n            message += '\",response=\"'+str(result, 'utf8')+'\"\\r\\n'\n            \n        message += \"Content-Length: 0\\r\\n\\r\\n\"\n        \n        return message\n    \n    def Trying(self, response):\n        message = \"SIP\/2.0 100 Trying\\r\\n\"\n        message += \"Via: SIP\/2.0\/UDP \"+response.headers['Via']['address']+\";branch=\"+response.headers['Via']['branch']+\"\\r\\n\"\n        message += \"From: \"+response.headers['From']['sip_url']+\";tag=\"+response.headers['From']['tag']+\"\\r\\n\"\n        message += \"To: \"+response.headers['To']['sip_url']+\"\\r\\n\"\n        message += \"Call-ID: \"+response.headers['Call-ID']+\"\\r\\n\"\n        message += \"CSeq: \"+response.headers['CSeq']['check']+\" \"+response.headers['CSeq']['method']+\"\\r\\n\"\n        message += \"Max-Forwards: 70\\r\\n\"\n        message += \"Content-Length: 0\\r\\n\\r\\n\"\n        \n        return message\n\n    def Ringing(self, response,tag):\n        message = \"SIP\/2.0 180 Ringing\\r\\n\"\n        message += \"Via: SIP\/2.0\/UDP \"+response.headers['Via']['address']+\";branch=\"+response.headers['Via']['branch']+\"\\r\\n\"\n        message += \"From: \"+response.headers['From']['sip_url']+\";tag=\"+response.headers['From']['tag']+\"\\r\\n\"\n        message += \"To: \"+response.headers['To']['sip_url']+\";tag=\"+tag+\"\\r\\n\"\n        message += \"Call-ID: \"+response.headers['Call-ID']+\"\\r\\n\"\n        message += \"CSeq: \"+response.headers['CSeq']['check']+\" \"+response.headers['CSeq']['method']+\"\\r\\n\"\n        message += \"Contact: <sip:\"+self.username+\"@\"+self.myIP+\">\\r\\n\"\n        message += \"Content-Length: 0\\r\\n\\r\\n\" \n        self.tagLibrary[response.headers['Call-ID']] = tag\n        \n        return message\n\n    def Ok(self, response):\n        message = \"SIP\/2.0 200 OK\\r\\n\"\n        message += \"Via: SIP\/2.0\/UDP \"+response.headers['Via']['address']+\";branch=\"+response.headers['Via']['branch']+\"\\r\\n\"\n        message += \"From: \"+response.headers['From']['sip_url']+\";tag=\"+response.headers['From']['tag']+\"\\r\\n\"\n        message += \"To: \"+response.headers['To']['sip_url']+\";tag=\"+response.headers['To']['tag']+\"\\r\\n\"\n        message += \"Call-ID: \"+response.headers['Call-ID']+\"\\r\\n\"\n        message += \"CSeq: \"+response.headers['CSeq']['check']+\" \"+response.headers['CSeq']['method']+\"\\r\\n\"\n        message += \"Content-Length: 0\\r\\n\\r\\n\"\n        \n        return message\n      \n    def Ack(self, response):\n        tag = self.tagLibrary[response.headers['Call-ID']]\n        message = \"ACK \"+response.headers['To']['sip_url'].strip('<').strip('>')+\" SIP\/2.0\\r\\n\"\n        message += \"Via: SIP\/2.0\/UDP \"+self.myIP+\":\"+str(self.port)+\";branch=\"+response.headers['Via']['branch']+\"\\r\\n\"\n        message += \"Max-Forwards: 70\\r\\n\"\n        if response.headers['To']['tag'] == '':\n            message += \"To: \"+response.headers['To']['sip_url']+\"\\r\\n\"\n        else:\n            message += \"To: \"+response.headers['To']['sip_url']+\";tag=\"+response.headers['To']['tag']+\"\\r\\n\"\n        message += \"From: \"+response.headers['From']['sip_url']+\";tag=\"+tag+\"\\r\\n\"\n        message += \"Call-ID: \"+response.headers['Call-ID']+\"\\r\\n\"\n        message += \"CSeq: \"+str(response.headers['CSeq']['check'])+\" ACK\\r\\n\"\n        message += \"Content-Length: 0\\r\\n\\r\\n\"\n    \n        return message\n            \n    def start(self):\n    \n       #ctl+c#\n        signal.signal(signal.SIGINT, signal.SIG_DFL)\n        self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        \n        try:\n            self.s.bind((self.myIP, self.port))\n        except OSError as e:\n            print(e)\n\n        response = \"\"\n\n        message = self.Register(response)\n        print(message)\n        self.s.sendto(message.encode('utf8'), (self.server, self.port))\n\n        readbuf = self.s.recv(8192)\n        response = SIP_message(readbuf)\n        print(readbuf.decode('utf-8'))\n\n        message = self.Register(response)\n        print(message)\n        self.s.sendto(message.encode('utf8'), (self.server, self.port))\n\n        readbuf = self.s.recv(8192)\n        response = SIP_message(readbuf)\n        print(readbuf.decode('utf-8'))\n\n        while True:\n            readbuf = self.s.recv(8192)\n            print(readbuf.decode('utf-8'))\n            response = SIP_message(readbuf)\n            \n            if response.headers['CSeq']['method'] == 'INVITE' and response.headers['Content-Length'] != 0:\n                sip_url = response.headers['From']['sip_url']\n                phone_num = re.search(r'sip:(.*)@',sip_url).group(1)\n                \n                call_id_buf = re.search(r'(.*)@',response.headers['Call-ID'])\n                if call_id_buf is None:\n                  call_id = response.headers['Call-ID']\n                else:\n                  call_id = call_id_buf.group(1)\n                \n                print('###################')\n                print('Incoming number=',phone_num)\n                print('###################')\n                \n                trying = self.Trying(response)\n                self.s.sendto(trying.encode('utf8'), (self.server, self.port))\n                print(trying)\n                tag = self.Tag()\n                ringing = self.Ringing(response,tag)\n                self.s.sendto(ringing.encode('utf8'), (self.server, self.port))\n                print(ringing)\n\n            elif response.headers['CSeq']['method'] == 'CANCEL':\n                ok = self.Ok(response)\n                self.s.sendto(ok.encode('utf8'), (self.server, self.port))\n                print(ok)\n\n        s.close()\n\nsip = SIP_connect(SERVER_IP, PORT, ID, PASS, MY_IP)\n\nsip.start()\n<\/copy><\/pre>\n\n\n\n<p>sip_client.py\u306e\u5b9f\u884c\u7d50\u679c(Asterisk\u8d77\u52d5\u3057\u3066\u3044\u308b\u524d\u63d0)<\/p>\n\n\n\n<p>SIP\u30b5\u30fc\u30d0\u30fc\u306b\u30bd\u30d5\u30c8\u30d5\u30a9\u30f3\u5185\u7dda21\u3092\u767b\u9332\u3059\u308b\u3002<br>\u2193<br>SIP\u30b5\u30fc\u30d0\u30fc\u306b\u81ea\u5206\u5185\u7dda20\u3092\u767b\u9332\u3059\u308b\u3002<br>\u2193<br>\u30bd\u30d5\u30c8\u30d5\u30a9\u30f3\u5185\u7dda21\u304c\u3089\u5185\u7dda20\u306b\u96fb\u8a71\u3092\u304b\u3051\u308b\u3002<br>\u2193<br>\u30bd\u30d5\u30c8\u30d5\u30a9\u30f3\u5185\u7dda21\u304c\u3089\u5185\u7dda20\u306e\u547c\u51fa\u3057\u3092\u6b62\u3081\u308b\u3002<\/p>\n\n\n\n<pre style=\"line-height: 12px;font-size: 12px; background: #eeeeee; overflow-x: scroll;overflow-y: hidden; padding: 10px 0 10px 1em;\"><font color=\"#ff0000\">REGISTER sip:192.168.0.201 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nMax-Forwards: 70\nContact: &lt;sip:20@192.168.0.41&gt;\nTo: &lt;sip:20@192.168.0.201&gt;\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=5cc014e4\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nCSeq: 1 REGISTER\nExpires: 3600\nContent-Length: 0\n<\/font>\n<font color=\"#0000FF\">\nSIP\/2.0 401 Unauthorized\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;rport=5060;received=192.168.0.41;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=5cc014e4\nTo: &lt;sip:20@192.168.0.201&gt;;tag=z9hG4cK6b86b273ff34fce19d6b804ef\nCSeq: 1 REGISTER\nWWW-Authenticate: Digest realm=\"asterisk\",nonce=\"1768112133\/88d496d35b71d7dd9b449e4892cbd71c\",opaque=\"6f3e8fba6e7d9a17\",algorithm=MD5,qop=\"auth\"\nServer: Asterisk PBX 23.0.0\nContent-Length:  0\n\n<\/font>\n<font color=\"#ff0000\">\nREGISTER sip:192.168.0.201 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nMax-Forwards: 70\nContact: &lt;sip:20@192.168.0.41&gt;\nTo: &lt;sip:20@192.168.0.201&gt;\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=c205ddd4\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nCSeq: 2 REGISTER\nExpires: 3600\nAuthorization: Digest username=\"20\",realm=\"asterisk\",nonce=\"1768112133\/88d496d35b71d7dd9b449e4892cbd71c\",uri=\"sip:192.168.0.201\",response=\"f117c90fc8812415eec31580fbeaaec6\"\nContent-Length: 0\n<\/font>\n<font color=\"#0000FF\">\nSIP\/2.0 200 OK\nVia: SIP\/2.0\/UDP 192.168.0.41:5060;rport=5060;received=192.168.0.41;branch=z9hG4cK6b86b273ff34fce19d6b804ef\nCall-ID: d4735e3a265e16eee03f59718b9b5d03@192.168.0.41:5060\nFrom: &lt;sip:20@192.168.0.201&gt;;tag=c205ddd4\nTo: &lt;sip:20@192.168.0.201&gt;;tag=z9hG4cK6b86b273ff34fce19d6b804ef\nCSeq: 2 REGISTER\nDate: Sun, 11 Jan 2026 06:15:33 GMT\nContact: &lt;sip:20@192.168.0.41&gt;;expires=3599\nExpires: 3600\nServer: Asterisk PBX 23.0.0\nContent-Length:  0\n<\/font>\n\n<font color=\"#0000FF\">\nINVITE sip:20@192.168.0.41 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.201:5060;rport;branch=z9hG4bKPjc42f673a-1751-4623-a8bd-48c3aa305c79\nFrom: \"21\" &lt;sip:21@192.168.0.201&gt;;tag=aa435736-c3b2-4ba1-a00e-5ceeb79d3e3d\nTo: &lt;sip:20@192.168.0.41&gt;\nContact: &lt;sip:asterisk@192.168.0.201:5060&gt;\nCall-ID: d2c00c2d-7114-4440-bb1c-a216954d11e9\nCSeq: 10033 INVITE\nAllow: OPTIONS, REGISTER, SUBSCRIBE, NOTIFY, PUBLISH, INVITE, ACK, BYE, CANCEL, UPDATE, PRACK, INFO, MESSAGE, REFER\nSupported: 100rel, timer, replaces, norefersub, histinfo\nSession-Expires: 1800\nMin-SE: 90\nMax-Forwards: 70\nUser-Agent: Asterisk PBX 23.0.0\nContent-Type: application\/sdp\nContent-Length:   237\n\nv=0\no=- 506936747 506936747 IN IP4 192.168.0.201\ns=Asterisk\nc=IN IP4 192.168.0.201\nt=0 0\nm=audio 11548 RTP\/AVP 0 101\na=rtpmap:0 PCMU\/8000\na=rtpmap:101 telephone-event\/8000\na=fmtp:101 0-16\na=ptime:20\na=maxptime:140\na=sendrecv\n<\/font>\n<font color=\"#00FF00\">\n###################\nIncoming number= 21\n###################\n<\/font>\n<font color=\"#ff0000\">\nSIP\/2.0 100 Trying\nVia: SIP\/2.0\/UDP 192.168.0.201:5060;branch=z9hG4bKPjc42f673a-1751-4623-a8bd-48c3aa305c79\nFrom: \"21\" &lt;sip:21@192.168.0.201&gt;;tag=aa435736-c3b2-4ba1-a00e-5ceeb79d3e3d\nTo: &lt;sip:20@192.168.0.41&gt;\nCall-ID: d2c00c2d-7114-4440-bb1c-a216954d11e9\nCSeq: 10033 INVITE\nMax-Forwards: 70\nContent-Length: 0\n\n\nSIP\/2.0 180 Ringing\nVia: SIP\/2.0\/UDP 192.168.0.201:5060;branch=z9hG4bKPjc42f673a-1751-4623-a8bd-48c3aa305c79\nFrom: \"21\" &lt;sip:21@192.168.0.201&gt;;tag=aa435736-c3b2-4ba1-a00e-5ceeb79d3e3d\nTo: &lt;sip:20@192.168.0.41&gt;;tag=006c7dc6\nCall-ID: d2c00c2d-7114-4440-bb1c-a216954d11e9\nCSeq: 10033 INVITE\nContact: &lt;sip:20@192.168.0.41&gt;\nContent-Length: 0\n<\/font>\n<font color=\"#0000FF\">\nCANCEL sip:20@192.168.0.41 SIP\/2.0\nVia: SIP\/2.0\/UDP 192.168.0.201:5060;rport;branch=z9hG4bKPjc42f673a-1751-4623-a8bd-48c3aa305c79\nFrom: \"21\" &lt;sip:21@192.168.0.201&gt;;tag=aa435736-c3b2-4ba1-a00e-5ceeb79d3e3d\nTo: &lt;sip:20@192.168.0.41&gt;\nCall-ID: d2c00c2d-7114-4440-bb1c-a216954d11e9\nCSeq: 10033 CANCEL\nReason: Q.850;cause=127\nMax-Forwards: 70\nUser-Agent: Asterisk PBX 23.0.0\nContent-Length:  0\n<\/font>\n<font color=\"#ff0000\">\nSIP\/2.0 200 OK\nVia: SIP\/2.0\/UDP 192.168.0.201:5060;branch=z9hG4bKPjc42f673a-1751-4623-a8bd-48c3aa305c79\nFrom: \"21\" &lt;sip:21@192.168.0.201&gt;;tag=aa435736-c3b2-4ba1-a00e-5ceeb79d3e3d\nTo: &lt;sip:20@192.168.0.41&gt;;tag=\nCall-ID: d2c00c2d-7114-4440-bb1c-a216954d11e9\nCSeq: 10033 CANCEL\nContent-Length: 0\n<\/font>\n<br><\/font><\/pre>\n\n\n\n<p>SIP\u30b5\u30fc\u30d0\u30fc\u3068\u5185\u7dda\u96fb\u8a71\u306e\u30b7\u30fc\u30b1\u30f3\u30b9<\/p>\n\n\n\n<pre style=\"line-height: 15px;font-size: 15px; background: #eeeeee; padding: 10px 0 10px 1em;\">             \u5185\u7dda20                    SIP\u30b5\u30fc\u30d0\u30fc               \u5185\u7dda21\n\n              |                          |                          |\n              |                          |    REGISTER no sdp       |\n              |                          |<-------------------------|\n              |                          |    401 Unauthorized      |\n              |                          |------------------------->|\n              |                          |    REGISTER no sdp PA    |\n              |                          |<-------------------------|\n              |                          |    200 OK                |\n              |                          |------------------------->|\n              |<font color=\"#ff0000\">(1) REGISTER no sdp<\/font>       |                          |\n              |<font color=\"#ff0000\">-------------------------><\/font>|                          |\n              |<font color=\"#0000ff\">(2) 401 Unauthorized<\/font>      |                          |\n              |<font color=\"#0000ff\"><-------------------------<\/font>|                          |\n              |<font color=\"#ff0000\">(3) REGISTER no sdp PA<\/font>    |                          |\n              |<font color=\"#ff0000\">-------------------------><\/font>|                          |\n              |<font color=\"#0000ff\">(4) 200 OK<\/font>                |                          |\n              |<font color=\"#0000ff\"><-------------------------<\/font>|                          |\n              |                          |    INVITE no sdp         |\u5185\u7dda20\u3092\u547c\u51fa\u3059\n              |                          |<-------------------------|\n              |                          |    401 PAR               |\n              |                          |------------------------->|\n              |                          |    ACK                   |\n              |                          |<-------------------------|\n              |                          |    INVITE sdp PA         |\n              |                          |<-------------------------|\n\u5185\u7dda20\u304b\u3089\u7740\u4fe1|<font color=\"#0000ff\">(5) INVITE sdp<\/font>            |                          |\n              |<font color=\"#0000ff\"><-------------------------<\/font>|                          |\n              |<font color=\"#ff0000\">(6) 100 Trying<\/font>            |                          |\n              |<font color=\"#ff0000\">-------------------------><\/font>|                          |\n              |                          |    100 Trying            |\n              |                          |------------------------->|\n              |<font color=\"#ff0000\">(7) 180 Ringing<\/font>           |                          |\n              |<font color=\"#ff0000\">-------------------------><\/font>|                          |\n              |                          |    180 Ringing           |\n              |                          |------------------------->|\n              |                          |                          |\n              |                          |    CANCEL                |\u547c\u51fa\u3092\u6b62\u3081\u308b\n              |                          |<-------------------------|\n  \u547c\u51fa\u304c\u6b62\u307e\u308b|<font color=\"#0000ff\">(8) CANCEL<\/font>                |                          |\n              |<font color=\"#0000ff\"><-------------------------<\/font>|                          |\n              |<font color=\"#ff0000\">(9) 200 OK<\/font>                |                          |\n              |<font color=\"#ff0000\">-------------------------><\/font>|                          |\n              |                          |    200 OK                |\n              |                          |------------------------->|\n              |                          |                          |\n\n<\/pre>\n\n\n\n<p>\u7740\u4fe1\u756a\u53f7\u306f\u3001INVITE\u306e\u300cFrom: &#8220;21&#8221; &lt;sip:21@192.168.0.201&gt;\u300d\u306e\u300c21\u300d\u3067\u3059\u3002<\/p>\n\n\n\n<center><font size=\"3\"><a href=\"https:\/\/team-okada.com\/?p=882\" rel=\"prev\"><<\u524d\u306e\u8a18\u4e8b\u3078<\/a>&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;\n<\/font><\/center>\n","protected":false},"excerpt":{"rendered":"<p>Python\u306esocket\u3092\u4f7f\u7528\u3057\u3066UDP\u901a\u4fe1\u3067SIP\u30b5\u30fc\u30d0\u30fc\u306bREGISTER \u30ea\u30af\u30a8\u30b9\u30c8\u3092\u884c\u3044\u3001IP \u30a2\u30c9\u30ec\u30b9\u3092&nbsp;SIP\u30b5\u30fc\u30d0\u30fc\u306b\u767b\u9332\u3057\u307e\u3059\u3002 IP\u96fb\u8a71\u304cUDP\u30d7\u30ed\u30c8\u30b3\u30eb\u3092\u4f7f\u7528\u3059\u308b\u7406\u7531\u3000UDP (User  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-926","post","type-post","status-publish","format-standard","hentry","category-asterisk"],"_links":{"self":[{"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/posts\/926","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/team-okada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=926"}],"version-history":[{"count":69,"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/posts\/926\/revisions"}],"predecessor-version":[{"id":1048,"href":"https:\/\/team-okada.com\/index.php?rest_route=\/wp\/v2\/posts\/926\/revisions\/1048"}],"wp:attachment":[{"href":"https:\/\/team-okada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=926"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/team-okada.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=926"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/team-okada.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}