tcp连接后就可以异步读数据了,如:
asio::async_read(socket...
如果remote endpoint关闭,此时再发起asio::async_read会出现错误,提示"系统找不到指定的文件",实际上是socket已经无效了,错误号2,自然不能从socket上读取数据。
1. socket.local_endpoint() 返回的ip是 "0.0.0.0", 而不是本机IP地址,0.0.0.0 is the "any" address
要获取本机IP请参考:
tcp::resolver resolver(io_service);
tcp::resolver::query query(host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
2. io_service.run()阻塞问题
Actually, io_service.run() blocks if it has "work" to do.
In general, "work" means an unfinished asynchronous operation.
3. Async Chat example questions, why post()?
|
Re: [asio-users] Async Chat example questions
From: Christopher Kohlhoff <chris@ko...> - 2006-08-03 07:58
|
Hi Andrew,
kingos@op... wrote: > Some more questions from chat_client.cpp > > 1. How many threads end up running (is it 2 or 3)?
The actual answer depends on the platform you run on, but from the application's point of view it's 2. The two threads are:
* The main thread, which is responsible for reading the input from the user.
* The io_service.run() thread, which is used to perform all actions associated with the chat_client object.
> ie. does async_write spawn a new thread or anything?
No.
> 2. Related to 1, why does the function write() call post > straight away? why not just call async_write? Since it does > call post, why then call async_write from the other thread, if > you are just putting it in a queue to be processed by the same > thread?
The data members of the chat_client object are (deliberately) not thread safe. Therefore it is necessary to ensure that all accesses to these members are synchronised in some way. This means it is not safe to call async_write directly on the socket from the main thread when the socket might also be accessed from the background thread.
In this example, thread safety is achieved by ensuring that the members are only accessed from within handlers that were dispatched through the io_service.post() call. The io_service provides a guarantee that any handlers passed to io_service.post() (or io_service.dispatch()) are only invoked from inside a call to io_service.run(). As there is only one thread calling io_service.run() in this example, the chat_client data members will only ever be accessed from one thread.
> 3. Why is there no check necessary for if the socket has > connected succesfully or not? is this because the write > function is posted to the t thread, and it will be busy > connecting to the server? Or is this just an oversight?
Just an oversight.
> 4. If you wanted to send a connect event back to the int > main() thread, how would you do that? can you do an > io_service::post the other way? can you somehow obtain the > main thread from the io_service?
In this example, it's a bit difficult to do, since the main thread is blocked waiting for input from the user. However in general you can indeed have an io_service object per-thread if you want to pass events from one thread to another.
> 5. Why at the end of the main function is t.join() called. > Could you instead call io_service.run()?
No, since that would mean we'd lose the thread safety guarantee described in the answer to 2.
> If the answer to question 1 was that there are 3 threads > running (ie. async_write goes to another thread), what is the > point of spawning this thread?
The io_service::run() thread is only needed because the main thread has to block on the input from the user. If your program doesn't need to block on user input in that particular way, then you don't need the extra thread and can simply call io_service::run() from the main thread. This is what most of the other examples do.
Cheers, Chris
|
|
4. 线程安全
Re: [asio-users] Thread Safety: Shared objects: Unsafe.
From: Christopher Kohlhoff <chris@ko...> - 2007-01-26 22:39
|
Hi Boris,
On Fri, 26 Jan 2007 14:21:08 +0000 (UTC), "Boris" <monade@gm...> said: > Hi, What does the statement above from the docs mean for asio objects? > Is it allowed to call two different member functions of a shared > object from two different threads?
No.
> Or is it generally unsafe to access a shared object from different > threads concurrently?
Yes.
Only objects marked "Shared objects: Safe" can be accessed from different threads concurrently. An io_service object provides this level of safety, for example.
> My use case is to run a gui in the main thread and doing asio stuff in > a secondary thread. For syncing I use io_service::post for one > direction and gui event handling for the other. > > For example: > 1. Is it safe to call basic_datagram_socket::close() from the main > thread while a secondary thread is running the socket?
If by running the socket you mean accessing any member functions of the socket (async_send, async_receive or whatever) then this is not safe.
> 2. Same question for basic_deadline_timer::cancel(). Or do I have to > wrap this call with ioService.post( boost::bind( > &deadline_timer::cancel, &myTimer))?
Again, calling cancel() directly is not safe.
For both 1 and 2, a good solution is to do as you suggest and use io_service::post() to ensure that all operations are performed in the one thread.
> asio objects have lots of member functions. How do I know which ones > are safe to use concurrently in the described sense?
For the moment, you should consider none of the member functions safe to use concurrently.
However, in the future there will probably be a change to asio's guarantees to specify that concurrent "read" operations are safe. This is being discussed by the C++ committee with respect to threads support in C++. What a "read" operation means is yet to be defined, but is probably a const member function. In this case, the socket and timer objects would provide the following thread-safety guarantees:
write + write: unsafe read + write: unsafe read + read: safe
(Asio objects may already meet this requirement, but I have not yet audited the code to make sure.)
In any case, as both basic_datagram_socket::close() and basic_deadline_timer::cancel() are write operations you would still have to do something like io_service::post() to make it safe.
Cheers, Chris |