• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Sockets slow on Macintosh
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Sockets slow on Macintosh


  • Subject: Sockets slow on Macintosh
  • From: Tron Thomas <email@hidden>
  • Date: Tue, 05 Apr 2005 15:39:24 -0700

I am working on a cross platform project that takes a long time to start up on the Macintosh. Some investigates indicate that a large portion of the slowness is related to the use of sockets for communicating information between different processes.

To test this idea, I have written a much simpler client/server implementation that simulates what the original code tries to do. I ran this new implementation on an G4 iMac with 512 Megabytes of RAM, running at 800 Megahertz, and using Mac OS X 10.3.8. I sent 370 text messages from the client to the server. The process took over a minute and a half to complete. I ran the same program on an Intel Pentium IV with 512 Megabytes of RAM, running at 1.7 Gigahertz, and using Fedora Core 3 Linux. That system took just over 5 seconds to complete the same number of iterations.

Given that the Intel system can perform the program so quickly, what can be changed in the code so the Macintosh can have comparable speed? Below are the source listing both the client and server, the Makefile for building the programs, and a Bash shell script used to aid in testing. I would appreciated any feedback, anyone has to offer.

+-------------+
| Server Code |
+-------------+
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h> // needed for strerror
#include <errno.h>

#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>

using std::string;

namespace
{
  void ThrowError
  (
     const char* pszPrefix
  )
  {
     string strError = pszPrefix;
     strError += ::strerror(errno);
     strError += '\n';
     throw std::runtime_error(strError);
  }
}

int main()
{
const short nPORT = 8979;
const int nMAXIMUM_CONNECTIONS = 5;
const int nINVALID_SOCKET = -1;
using std::cerr;
using std::clog;
using std::cout;
int nServerSocket = ::socket(AF_INET, SOCK_STREAM, 0);
if(0 == nServerSocket){
cerr << "Failed to create the server socket.\n";
return 0;
}


sockaddr_in address;
::memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = ::inet_addr("127.0.0.1");
address.sin_port = htons(nPORT);
int connection = nINVALID_SOCKET;
try{
if(0 > ::bind(nServerSocket, reinterpret_cast<sockaddr*>(&address),
sizeof(address))){
::ThrowError("The following error occurred binding to the server "
"socket:\n");
}
if(0 > ::listen(nServerSocket, nMAXIMUM_CONNECTIONS)){
::ThrowError("The following error occurred creating the listening "
"queue.\n");
}


     cout << "The server is running and waiting for connections.\n";

bool bRun = true;
while(bRun){
fd_set readSet;
FD_ZERO (&readSet);
FD_SET(nServerSocket, &readSet);
timeval timeout = {5, 0};
int nResult = ::select(FD_SETSIZE, &readSet, NULL, NULL, &timeout);
if(0 > nResult){
::ThrowError("The following error occurred while waiting for a "
"connection:\n");
}
if(0 == nResult){
clog << "Timed out waiting for a connection.\n";
continue;
}
cout << "Accepting a client connection.\n";
if(FD_ISSET(nServerSocket, &readSet)){
sockaddr_in client_address = address;
socklen_t client_address_len =
static_cast<socklen_t>(sizeof(client_address));
connection = ::accept(nServerSocket,
reinterpret_cast<sockaddr*>(&client_address),
&client_address_len);
if(0 > connection){
::ThrowError("The following error occrured accepting a client "
"connection:\n");
}
}


size_t bufferSize;
nResult = ::recv(connection, &bufferSize, sizeof(bufferSize), 0);
if(nResult != sizeof(bufferSize)){
::ThrowError("The follow error occurred trying to read the buffer "
"size:\n");
}


        std::vector<char> buffer(bufferSize);
        nResult = ::recv(connection, &(buffer[0]), bufferSize, 0);

string message;
if(nResult == static_cast<int>(bufferSize)){
message.assign(buffer.begin(), buffer.end());
}
else
{
::ThrowError("The following error ocurred reading the text:\n");
}
if(0 == message.compare("stop")){
clog << "Stopping the server.\n";
bRun = false;
}
else{
clog << "Received the following client data:\n"; << message << '\n';
}


message = "?return_code=PASS";
size_t length = message.size();
nResult = ::send(connection, &length, sizeof(length), 0);
if(sizeof(length) != nResult){
::ThrowError("The following error occurred sending the message "
"reply size.\n");
}


nResult = ::send(connection, message.c_str(), length, 0);
if(nResult != static_cast<int>(length)){
::ThrowError("The following error occurred sending the reply "
"message.\n"); }
::close(connection);
connection = nINVALID_SOCKET;
}
}
catch(const std::exception& error){
cerr << error.what() << std::endl;
if(nINVALID_SOCKET != connection){
::close(connection);
connection = nINVALID_SOCKET;
}
}
::close(nServerSocket);


  return 0;
}

+-------------+
| Client Code |
+-------------+
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h> // needed for strerror
#include <stdlib.h>
#include <errno.h>

#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>

using std::string;

namespace
{
void ThrowError
(
const char* pszPrefix
)
{
string strError = pszPrefix;
strError += ::strerror(errno);
strError += '\n';
throw std::runtime_error(strError);
}
char RandomChar()
{
return(' ' + (::rand() % 95));
}
void CreateRandomMessage
(
string* pstrMessage
)
{
if(NULL == pstrMessage){
return;
}
pstrMessage->erase();
size_t size = ::rand() % 100;
// Allow only an 8% chance of large size buffers
if(size >= 8){
size = 40 + ::rand() % 40;
}
else{
size = 100 + ::rand() % 250;
}
std::insert_iterator<string> insert(*pstrMessage, pstrMessage->begin());
std::generate_n(insert, size, RandomChar);
}
}


int main
(
int nArgumentCount,
const char* pszArguments[]
)
{
const short nPORT = 8979;
using std::cerr;
using std::clog;
using std::cout;


  int nServerSocket = ::socket(AF_INET, SOCK_STREAM, 0);
  if(0 > nServerSocket){
     cerr << "Failed to create the server socket.\n";
     return 0;
  }

  try{
     sockaddr_in serverAddress;
     ::memset(&serverAddress, 0, sizeof(serverAddress));
     serverAddress.sin_family = AF_INET;
     serverAddress.sin_addr.s_addr = ::inet_addr("127.0.0.1");
     serverAddress.sin_port = htons(nPORT);

cout << "Connecting to the server...\n";
int nResult = ::connect(nServerSocket,
reinterpret_cast<sockaddr*>(&serverAddress),
sizeof(serverAddress));
if(0 != nResult){
::ThrowError("The following error occurred establishing a connection "
"to the server:\n");
}
string strMessage;
if(1 < nArgumentCount){
strMessage = pszArguments[1];
}
else{
::srand(::getpid());
::CreateRandomMessage(&strMessage);
}
size_t length = strMessage.size();
clog << "Sending " << length << " bytes of data to the server.\n";
nResult = ::send(nServerSocket, &length, sizeof(length), 0);
if(0 > nResult){
::ThrowError("The following error occurred sending data size:\n");
}


nResult = ::send(nServerSocket, strMessage.c_str(), length, 0);
if(nResult == static_cast<int>(length)){
clog << "Sent message '" << strMessage << "' to the server.\n";
} else{
::ThrowError("The following error occurred sending data:\n";);
}


cout << "Waiting for the server reply...\n";
size_t bufferSize;
nResult = ::recv(nServerSocket, &bufferSize, sizeof(bufferSize), 0);
if(0 > nResult){
::ThrowError("The following error occurred reading the buffer "
"size:\n");
}


std::vector<char> buffer(bufferSize);
nResult = ::recv(nServerSocket, &(buffer[0]), bufferSize, 0);
if(nResult != static_cast<int>(bufferSize)){
::ThrowError("The following error occurred getting the reply data.\n");
}
string strReply(buffer.begin(), buffer.end());
clog << "The server replied with '" << strReply << "'.\n";
}
catch(const std::exception& error){
cerr << error.what() << std::endl;
}
::close(nServerSocket);
return 0;
}


+----------+
| Makefile |
+----------+
CXX = /usr/bin/g++
CFLAGS = -g3 -Wall -ansi -pedantic

.SUFFIXES: .cpp

.cpp.o:
   $(CXX) $(CFLAGS) -c $< -o $@

all: Server Client

Server: Server.o
   $(CXX) -Wall $< -o $@

Client: Client.o
   $(CXX) -Wall $< -o $@

clean:
   rm -f Client
   rm -f Server
   rm -f *.o

+--------------+
| Shell Script |
+--------------+
#! /bin/sh

if [ $# -gt 0 ]; then
  passes=$1
else
  passes=10
fi

echo "Running $passes test passes..."

while [ $passes -gt 0 ]
do
  ./Client
  passes=$[$passes - 1]
  echo "$passes passes left."
done

./Client stop

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Sockets slow on Macintosh
      • From: Vincent Lubet <email@hidden>
    • Re: Sockets slow on Macintosh
      • From: Quinn <email@hidden>
    • Re: Sockets slow on Macintosh
      • From: Cameron Kerr <email@hidden>
  • Prev by Date: Re: CFSocket callback question
  • Next by Date: Re: Sockets slow on Macintosh
  • Previous by thread: Re: CFSocket callback question
  • Next by thread: Re: Sockets slow on Macintosh
  • Index(es):
    • Date
    • Thread