bluez multi socket 구현 관련 질문입니다.

blackhush의 이미지

bluez를 socket통신을 이용해서 프로그램하고 있는데요.
1:1 통신을 잘되고 있습니다. 그런데 다중 통신은 영 감을 못잡겠네요.

일단 제가 구현한 내용을 말씀드리면

초기에 channel 7개를 모두 생성하고 (channel 별로 socket => bind => listen)

poll 함수를 이용해서 연결을 시도하는 client가 있을때 마다 accept를 해주는 방식으로

구현하고 하고 있습니다.

여기까지는 문제 없이 되는데 문제는 이제 부터 입니다.

예를 들어 channel1이 연결된 상태에서 channel2가 다시 연결되 었을때 fd 값을 구분해서

먼저 연결된 channel에서만 data를 계속해서 receive 하도록 했는데요.

이상태에서 channel2로 data를 전송하면 ENOTSOCK 에러가 발생하네요.

장황하게 말씀드려서 답변 주시기 힘드실것 같아 죄송하네요

질문을 요약하자면

1. bluez socket 통신을 사용할때 첫번째 연결된 client에서만 data를 받고 첫번째 연결된
client가 끊어지기 전까지 두번째 이후 연결되는 client는 연결 상태만 유지하고 data를 받지
않거나 다른 buf에 쌓아 놓는 것이 가능한가요?

2. ENOTSOCK 에러가 발생했을때엔 어떻게 해결을 해야하나요?

그럼 무지한 저에게 가르침 부탁드립니다.

안녕히 계세요~!

bestyt의 이미지

rfcomm채널별로 session이 만들어졌고, fd로 read를 하는 상황이라면, 각각의 session마다 별도의 thread를 둬서 read하신거죠? 만약 그렇게 안하고 한 thread에서 특정 session의 fd로 read를 계속 했고, 다른 fd에서는 버퍼가 쌓여서 넘쳤다면, 넘친 fd의 socket은 unavailable하게 되서 ENOTSOCK이 리턴될꺼 같네요. -ENOTSOCK은 file descriptor에 더이상 sock_operation function callback이 없을때 return되는 에러입니다.

blackhush의 이미지

bsetyt 님 말씀 감사합니다.
일단 저는 환경은 하나의 Thread를 이용해서 특정 session의 fd로 read를 하고 있고
추가로 연결되는 rfcomm들은 accept만을 유지 하게 하려고 하고 있습니다.

TCP/ip를 이용해서 socket통신을 보면 multi session 기능이 지원이 되는데 그와 같은 기능을
bluetooth로 지원하려고 하고 있습니다.
(첫번째 연결된 socket으로 들어오는 data만 처리하고 첫번째 연결된 socket이 끊어지기 전까지
두번째, 세번째 연결된 socket은 연결되어 buf size 만큼 date를 전송 받고 첫번째 연결된 socket이
끊어진 후에 buf에 쌓여 있던 data를 전송하는 것입니다.)

제가 아직 일자 무식 초보라 좀 기본적인 질문을 추가해서 몇가지 질문드리겠습니다.

1. session이 여러개 생성이 되면 session 마다 각각 buf가 kernel(bluez)단에서 알아서 할당되나요?

2. 1:1로 연결해서 Test를 해보니까 buf가 full이 되도 kernel단에서 알아서 흐름제가 되는 것 같은데요.
하나의 Thread에서 특정 session의 fd로 read를 하고 있는 상황에서 다른 fd에 data가 입력되어
buf가 full이 되면 1:1처럼 흐름제어가 되지 않고 바로 error가 발생하는 건가요?
그렇다면 한번에 하나의 fd에 대한 data만 흐름제어가 가능한건가요?

3. 제가 구현하고자하는 방식으로 구현이 가능은 한건가요?

ㅠㅠ

답변 부탁드립니다.


안녕하세요~!

한수 부탁드립니다.

bestyt의 이미지

네 제가 아는데까지 설명드려보겠습니다.

1. kernel영역에 buffer가 할당되어있습니다. fd(file descriptor)의 할당은 socket이 bind되어 accept되거나 connect했을때 생성되는데, fd가 할당되었단 얘기는 kernel영역에서 전송에 필요한 buffer가 할당되었다는 뜻이죠. 만약 user area에서 read()를 호출하면, kernel단의 buffer가 비어있으면, 호출이 block되었다가 buffer에 정보가 들어오면 바로 깨어나서 copy_to_user()로 user버퍼로 전송 바이트가 복사됩니다. 만약 kernel단의 buffer에 데이터가 들어있다면 바로 return되어 user area에서 읽을수있겠죠.

2. 얘기하신 사항은 TCP/IP의 socket이라면 가능할수있을지 모르나, BT의 RFCOMM을 쓰는 socket이라면 RFCOMM구현에서 timeout이 있어, 즉 일정시간안에 전송된 data를 read해가지 않으면 timeout이 걸려 socket이 자동으로 close되고, 그이후에 user area에서 read()할려고 하면 -ENOTSOCK에러가 발생하는거죠.

3. 빠르게 첫번째 session에 대한 fd를 읽고 close하고나서 두번째 세번째를 처리하면 될수도 있을거 같은데, 각각의 operation들이 다 timeout threadhold안에 들어와야겠죠.

blackhush의 이미지

귀하신 시간 내셔서 친절히 답변 주시니 감사할 따릅니다.

답변 주신 내용에서 많이 배웠습니다.

님께서 답변 주신 내용에서 추가 질문이 있습니다.(궁금한게 많네요...^^;;)

1.kernel단의 buffer가 비어 block되어 있는 상태에서 buffer에 data가 들어오면 user 버퍼로 복사된다고 하셨는데요.
user 버퍼로 복사하는 주체가 혹시 recv()함수를 말씀하시는건가요?
맞다면 kernnel buffer에 data가 들어와 있어와 있을때 recv()를 해서 read해가지 않으면 data가 사라지고 close가
된다는 건가요?

2. 제가 Test를 잘 못했는지는 모르지만 rfcomm을 이용해서 1:1로 통신했을때에 host 쪽 buffer가 full이되어 더 이상
Read를 하지 않아도 client에서 전송되는 data가 사라지지 않은 상태에서 연결도 유지하고 있는 것을 확인 했었는데요.
그렇다면 제가 사용하고 있는 BT RFCOMM에서 timeout이 없어서 그런건가요? (좀 헷갈리네요 ㅠㅠ)

3. 말씀해주신 것 처럼 하지 않고 첫번째 session이 connection된 후에 close 하지 않고 connection을 계속 유지
한 상태에서 두번째 세번째 처리를 하고 싶은데 그건 불가능한가요?

답변 부탁드려요~!

안녕하세요~!

한수 부탁드립니다.

bestyt의 이미지

모든 socket connection은 fd로 관리되고, operation은 기본 read/write() kernel API로 각각 독립적으로 작동합니다.
말씀해주신대로 하면 이론적으론 문제가 없을듯한데.. socket만들때 channel number맞게 적어주고, bind할때도 맞게 실행시켜주고, 할당받은 fd로 각각 read/write하면 문제없이 작동할듯한데요..

혹시 어떻게 구현하셨는지 소스코드나 psudo코드 적어줄수있나요? 커널 컴파일되고, bluetooth모듈을 debug로 컴파일해서 로그나오게해서 로그보면 더 정확할꺼 같지만, 소스코드상에 문제가 없는지 검증해보는게 빠를수있을거 같네요.

blackhush의 이미지

bestyt 님 관심가지고 답변해주셨는데...

늦어서 죄송합니다.

다른 일이 걸려서 이제야 글을 다네요...

일단 제가 좀 더 고민해봐야 겠네요.

님 답변으로 갈길은 정했습니다.

해보고 성공하면 다시 글남기겠습니다.

그럼 안녕히 계십시오.

안녕하세요~!

한수 부탁드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.