|
|
Browse by Tags
All Tags » Indigo » TCP/IP (RSS)
-
As I mentioned on the 30th anniversary of IP , an early and fundamental split was made in TCP to distinguish point-to-point messaging from end-to-end messaging. The split is based on a philosophy that the communication endpoints should be in control and that there should be a minimal amount of functionality and responsibility distributed along the communication path in between. The end-to-end philosophy shows up in how TCP systems perform throttling. Duplication of throttling makes the system more complicated. Duplication of throttling also makes the system less efficient because more throttling decisions have to be made by intermediaries that have less information about the system than the endpoints. TCP uses flow control to establish how fast data can be transmitted from the sender to the receiver. Rather than having the communication path adjust the flow rate, TCP uses congestion control algorithms to infer how the sender should change its transmission strategy to best use the network. In the basic implementation of TCP, the data stream is overlaid by a transmission window that defines which packets can be sent. As packets are received and acknowledged, the transmission window slides along the data stream. The endpoints grow and shrink the size of the transmission window as needed to adjust the flow rate. Initially the transmission window is very small because the state of the communication path is unknown. However, the window size adapts itself over time to an optimal rate of transmission. Some of the changes to the TCP/IP stack in Windows Vista were to accelerate the rate of adaptation and reduce the amount of time spent using a sub-optimal transmission rate. The end-to-end philosophy also shows up in how the WCF TCP channel avoids trying to do throttling. The service knows more about how it's going to use the network than the networking stack does. Consequently, if you want to control how quickly things are sent and received, the best place to control that is in the application. The only bottleneck in the TCP channel is how quickly it can pass information back and forth between the application and the wire. The default quota settings for the channel are sufficient for networks up to 100 Mbps. You'll want to increase the ConnectionBufferSize quota from its default of 8 KB to something like 64 KB on faster networks. Note that if the throttling is desired for fairness between applications rather than within an application, then the best place to do the throttling Read More...
|
-
How do I detect when the other side of a TCP connection has gone away? Does TCP keep-alive take care of this for me? Although we take it for granted that change can be quickly detected for closely connected components, it turns out to be surprisingly difficult to detect change when two machines are isolated by more than a simple wire. Even a really big change to the system, like one of the machines disappearing, is hard to spot. Detecting that the other side has disappeared is a common request because, on a server, knowing that the client has dropped the connection allows you to clean up resources much faster. The TCP transport sometimes gives you quick notifications by aborting the session that the connection has been dropped. However, there's no guarantee that the transport will be able to detect that the other side has gone away. That's because notification of a TCP connection reset has to travel just like any other piece of data and can be lost or redirected along the way, if it was sent at all. The only sure thing is that the next time you attempt an IO operation, you'll find out if the channel was still good or not. If you're unhappy waiting for the next IO operation, then you can make IO operations happen faster. The basic concept is to have a cheap IO operation that does nothing but bounce between the two parties. This is sometimes called a heartbeat and is exactly what takes place when you talk about TCP keep-alive. However, the standard keep-alive interval for TCP is 120 minutes, which is probably worse than your current latency for detecting change. By default, a service gets bored waiting after about 10 minutes and gives up. The chance of a keep-alive happening between the time that a client disconnects and the service notices it is pretty small. If you want something faster but don't want to change the timeouts, then you can take the basic concept into your own hands. One approach is to create a keep-alive method on your service contract that does nothing but let you trigger IO operations at a frequency you desire. Another approach is if you control both ends and don't want to change your service contract, then you can do the same thing in a protocol channel and swallow those messages so that the service never has to see them. Next time: Collections without CollectionDataContract Read More...
|
-
Can I configure non-HTTP web service activation from the command line? Yes, and you don't need any special tools if you're already familiar with configuring IIS from the command line. I've already talked about how to configure a new web site or application for activation in a previous post. Modifying the configuration uses the same appcmd program that is installed as part of the IIS scripting tools. It's installed on my system as %windir%\system32\inetsrv\appcmd.exe. All modifications to the web site are going to start with appcmd set site sitename and all modifications to the application are going to start with appcmd set app appname . The sitename and appname are the long path name for the web site or application, such as "Default Web Site" or "Default Web Site/myapp". The list of protocols for activation is associated with the application. Enabling an application to be activated using TCP would look like appcmd set app "Default Web Site/myapp" /enabledProtocols:net.tcp . The protocol configuration is associated with the web site. Each protocol configuration is called a binding (not related to a WCF binding) and corresponds to a protocol scheme, IP address list, port, and host header. Not all protocol schemes are going to support all of those other things. Adding a new configuration for TCP would look like appcmd set site "Default Web Site" -+bindings.[protocol='net.tcp',bindingInformation='808:*'] . That same binding would be deleted by changing the plus to a minus, appcmd set site "Default Web Site" --bindings.[protocol='net.tcp',bindingInformation='808:*'] . Changing the IIS configuration requires administrator approval. If you don't have permission to access the configuration file, you'll get an error that looks like this: ERROR ( message:Configuration error Filename: \\?\C:\Windows\system32\inetsrv\config\applicationHost.config Line Number: 0 Description: Cannot read configuration file . ) Next time: Address Filters that Swallow GET Read More...
|
-
Back in May I talked about the problem of getting client IP addresses , which you don't have any good way to solve today in WCF. There were a lot of strong comments on that post that this was a feature that people really needed. As it turns out, this was a feature that we wanted to get into Orcas but couldn't get approval. I took the same questions to TechEd to see what people would say. A lot of customers there really wanted this feature as well. The good news is that we were able to use all of that feedback to get the feature approved and into the product. When using the TCP and HTTP transports, you'll be able to get a message property off of each message that tells you the IP address and port number of the machine that sent the message. The bad news is that because this was a feature that we did very late, it wasn't done in time to appear in the beta releases. We've actually had this done for a few weeks but people continue to ask for the feature because we've had no way to tell you about it. Rather than let that continue, we decided to let you know that this was one of the things coming in the final release that you haven't had an opportunity to see yet. Phil Henning is the developer that worked to get this done and he's really wanted to talk about it in the meantime so for those of you that are interested, I'm going to let Phil give you more details about how the message property is used. You should expect to see a post on his blog later today. Read More...
|
-
What is the lifetime of a TCP session? The lifetime of the session object from a TCP transport channel lasts exactly as long as you own the underlying TCP connection. Once you give up ownership of the TCP connection, either by saying that you're done with it or by having it fault, the lifetime of the session is over. Closing the channel is a way of saying that you're done with the TCP connection. The TCP socket connection may still be usable and go back into a connection pool to be circulated to someone else. Having the TCP socket connection fail is one way to cause the TCP channel to fault. This definition of lifetime means that there's no way to recover a TCP session once it has been closed or faulted. If you need to have a recoverable session, then you need to need layer a new session on top of the TCP session, such as with reliable messaging. Layering a new session on top allows multiple TCP sessions to be created and destroyed without affecting the session that is visible to the user. Next time: Ownership of HTTP Connections Read More...
|
-
I have a machine with multiple network cards. How do I control which networks my service listens on? The answer to this question is going to be specific to the transport that you're using. I'll cover the HTTP and TCP transports that WCF ships with. Talking about addresses for the named pipe transport is less interesting because we don't allow remote connections with our named pipes! With custom transports, you're on your own and will have to contact the author. The TCP transport is very liberal with wildcarding addresses. When given a choice of multiple addresses for a machine, it will listen on all of them. To change this, you need to prevent the transport from having this choice. Here are the two things that you will need to do. First, make sure that the HostNameComparisonMode property for the transport is set to Exact. HostNameComparisonMode controls the address wildcard and the Exact option means that the hostname and port have to match exactly. Second, change the listening address of the service from a hostname to an explicit IP address. This guarantees that you'll get the specific network address that you want. Now, you've removed all choice from matching the address of the service, and you have a service that only listens on a single one of your multiple addresses. The HTTP transport is a little bit more flexible with wildcarding because it can leverage a feature built into the platform for HTTP. The HTTP.SYS driver allows you to define an IP Listen List that contains a particular set of IP addresses to listen on for HTTP connections. If you don't have a listen list configured, then by default the HTTP transport will be listening on all of the available network addresses, exactly like the TCP transport. The same technique for listening on just a single address with HostNameComparisonMode works for HTTP as it did for TCP. Finally, I thought it important to mention that just about every computer these days has multiple IP addresses- even if you don't have multiple network cards. You have a loopback IP address (127.0.0.1 for IPv4) that always corresponds to local connections and a real IP address from your network adapter. This means that you have everything you need to craft a "local machine"-only service even when not using named pipes. The guarantee when doing this is a little bit weaker than the one we make for named pipes though. We block remote users that are going through a local intermediary from named pipes by filtering on the origin of the account Read More...
|
-
IIS uses some inscrutable strings to configure the activatable bindings of a web site. Here's the minimum you need to interpret a binding and get started working with activation. Activation is controlled by the activationHost.config file. In the list of web sites, each site has a binding section that contains the list of supported protocols. < site name ="Default Web Site" id ="1" > < bindings > < binding protocol ="HTTP" bindingInformation ="*:80:" /> < binding protocol ="net.tcp" bindingInformation ="808:*" /> </ bindings > </ site > The format for the HTTP binding information comes from IIS. It has three parts separated by colons. The three parts are List of IP addresses to listen on (or a wildcard symbol) Port number List of host headers (or blank) The format for TCP was picked to be as similar as possible to what already existed for HTTP. We have two parts to configure, again separated by colons. There is no equivalent for the list of addresses. The two parts are Port number Host name comparison mode (blank or a wildcard symbol) Next time: Proxy Bypassing Behavior Read More...
|
-
My web service needs to periodically broadcast messages to clients. The service is an Internet-facing application hosted inside of IIS. What’s the best way to do this? The big limitation in this scenario is that your clients might be behind a firewall and non-addressable. There are basically two architecture camps for broadcasting messages to clients over the Internet. The push architecture camp has the clients maintain a continuous connection to the server and pushes data out at each update. The pull architecture camp has the clients periodically poll the server to see if there’s any new data. Both of these architectures are widely used and they trade latency versus resources off of each other. There are a few other architectures that work locally as well but aren’t as useful over the Internet, such as multicasting and callbacks. I’m just going to pick one of these and talk about using a push architecture. The basic way to build a push architecture is to have clients connect to the server and then the server holds the connection open indefinitely to send messages. If your service is hosted in IIS version 6 or below, then you don’t have a lot of choice about the network protocol. Pushing data from the server to client is difficult with HTTP because the protocol is built on top of the request-reply model. A typical way of using HTTP to push is to make an empty request and send back a response using the chunked transfer encoding. Chunked transfers allow an HTTP server to send the response in pieces without having to specify the total length of the response up front. Normally, the client knows the message is done when the connection is closed or the pre-announced content length is reached. Neither of those options work in this case. Instead, the server needs to define some framing protocol so that the client can tell when the individual messages are done. The easiest way to get chunked HTTP transfers in WCF is to use the HTTP transport with streaming enabled. If your service is hosted in IIS 7 (the Vista/Longhorn version of IIS), then you are able to pick other network protocols for your service, such as TCP. TCP is inherently duplex so it works across the Internet for server-initiated transfer of messages without having to connect back through a firewall. Since TCP is duplex, you can write a duplex contract that gives you a very nice programming model for sending the broadcasts. This is a lot less work on your part than the equivalent setup needed with HTTP. Read More...
|
-
I wrote the article on MEX endpoints about a month ago after someone asked the question on one of our internal mailing lists. I wrote the NetTcp Port Sharing sample about a month ago as well. Late at night I needed to test that the MEX endpoint code compiled before I posted the article so I just dropped it into the port sharing sample and tried it. Funny things can happen when you use two obscure features together. Of course, I picked the MEX address to use the same port as the regular client contract in the sample. ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); host.Description.Behaviors.Add(behavior); Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); string mexAddress = String.Format( "net.tcp://localhost:5555/mex/{0}" , salt); host.AddServiceEndpoint( typeof (IMetadataExchange), mexBinding, mexAddress); This works just fine when port sharing is turned off. Two endpoints in the same service host can share the same port without conflict. The port sharing feature is only needed to coordinate the sharing of ports across process boundaries. However, when you turn port sharing on, this breaks with an AddressAlreadyInUseException saying that there may already be someone listening on that IP address. An unlikely assertion! It turns out in this case that adding global port sharing actually prevents you from performing local port sharing. The reason for this is a bit non-obvious. Port sharing allows multiple processes to share the same port (obvious). However, every listener on the port must buy into the sharing arrangement. It wouldn’t work for three programs to share a port but a fourth to come in and demand exclusive access (obvious). What’s going wrong is that the MexTcpBinding has its own TCP transport with its own port sharing setting that is still set to the default off position (not obvious). One of the endpoints is trying to share the port with other processes but the other is demanding exclusive access for this process, causing the exception message that you see (painful). The workaround for this is to enable port sharing on the MEX binding as well (ugly). ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); host.Description.Behaviors.Add(behavior); Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); CustomBinding mexBinding2 = new CustomBinding(mexBinding); mexBinding2.Elements.Find<TcpTransportBindingElement>().PortSharingEnabled = true ; string mexAddress = String.Format( "net.tcp://localhost:5555/mex/{0}" Read More...
|
-
For the next few days I'm going to present a small sample I wrote to demonstrate the port sharing feature. The first part presents background information about the feature. I'm looking for feedback to help make the sample better. Right now, the sample configures the endpoints in code rather than configuration because it uses randomly-generated addresses for the server. I may just tack on the configuration details at the end because other port sharing topics already cover that material. The TCP/IP protocol uses a 16-bit number, called a port, to differentiate connections to multiple network applications running on the same machine. If an application is listening on a port, then all TCP traffic for that port goes to that application. Other applications cannot listen on that port at the same time. Many protocols have a standard or default port number that they use. For example, the HTTP protocol typically uses TCP port 80. Internet Information Services (IIS) has a listener to share a port between multiple HTTP applications. IIS listens on the port directly and forwards messages to the appropriate application based on information inside the message stream. This allows multiple HTTP applications to use the same port number without having to compete to reserve the port for receiving messages. Net.Tcp Port Sharing is a Windows Communication Foundation (WCF) feature that similarly allows multiple network applications to share a single port. The Net.Tcp Port Sharing Service accepts connections using the net.tcp protocol and forwards messages based on their destination address. The Net.Tcp Port Sharing Service is not enabled by default. Before running this sample, you will need to manually enable the service. For more information, see How to: Install and Configure Port Sharing (this is another document in the SDK but it looks like it's still being written so I'm not making this a link). If the service is disabled, an exception will be thrown when the server application is started. Unhandled Exception: System.ServiceModel.CommunicationException: The TransportManager failed to listen on the supplied URI using the NetTcpPortSharing service: failed to start the service because it is disabled. An administrator can enable it by running 'sc.exe config NetTcpPortSharing start= demand'.. ---> System.InvalidOperationException: Cannot start service NetTcpPortSharing on computer '.'. ---> System.ComponentModel.Win32Exception: The service cannot be started, either because it Read More...
|
|
|
|