Java Networking API vs. The C library networking API

The original article is located here.
In this article, I described what was involved in writing a server program in the C language. The details are not important, but I wanted to compare the details that are exposed in this relatively simple C network programming example with the equivalent Java code.

To accept an incoming connection and write a simple one line message to the client, the following is needed in C:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define DEFAULT_PROTOCOL 0
#define MAX_QUEUED_INCOMING 1024

static char opts[11] = “p:”;
int port = 5001;

void parseArgs(int argc, char *argv[])
{
char c = ‘\0’;;
while ((c = getopt(argc, argv, opts)) != -1)
{
switch (c)
{
case ‘p’:
port = atoi(optarg);
break;
default:
break;
}
}
}

int initServer(int server_port)
{
int server_sd = 0;
int serverLen = 0;
int rc = 0;
struct sockaddr_in my_addr;
char errBuf[256];
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_port = htons (server_port);
server_sd = socket (AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
if (server_sd == -1)
{
perror(“socket() failed”);
exit(-1);
}
rc = 0;
rc = bind(server_sd, (struct sockaddr *)&my_addr, (socklen_t)sizeof(my_addr));
if(rc==-1)
{
perror(“bind() failed”);
exit(-1);
}
rc= 0;
rc=listen(server_sd, MAX_QUEUED_INCOMING);
if(rc == -1)
{
perror(“listen() failed”);
exit(-1);
}
return server_sd;
}

int main(int argc, char *argv[])
{
int server_sd,client_sd,rc=0;
char buf[256];
struct sockaddr_in their_addr;
signal (SIGPIPE, SIG_IGN);
parseArgs(argc, argv);
server_sd = initServer(port);
while(1)
{
socklen_t their_addr_len = sizeof(their_addr);
client_sd = accept(server_sd,(struct sockaddr *)&their_addr, &their_addr_len);
if(client_sd != -1)
{
sprintf(buf, “connected to server: sd=%d\n”, client_sd);
rc = send(client_sd, buf, strlen(buf),MSG_NOSIGNAL);
if (rc==-1) //connection closes whether send()
{ //was successful or not.
close(client_sd);
continue;
}
close(client_sd);
} else {
perror(“accept() failed”);
continue;
}
client_sd=0;
}
return 0;
}

Note, I called this simple. Now, take a look at Server.java that was also used in the last series of articles. This program does basically the same thing as the above C program:

import java.net.*;
import java.io.*;

public class Server
{
public static void main(String [] args)
{
try {
ServerSocket server = new ServerSocket(Integer.parseInt(args[0]));
AcceptorThread at = null;
while(true)
{
Socket connection = server.accept();
OutputStream os = connection.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(“connected to the server\n”);
bw.flush();
bw.close();
osw.close();
os.close();
connection.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}

On the best day, I still prefer the C programming language, but one does have to admire what Sun accomplished with the Java networking API.

At the same time, this brevity has its price. There are many things you can do in C networking code that cannot be done in Java networking code. For example, Raw Sockets can not be used in Java code.