Sei sulla pagina 1di 33

Socket Programming in C

Computer Communication and Networks


Lab: 7 & 8
What is a socket?
 An interface between application and
network
 The application creates a socket
 The socket type dictates the style of
communication
• reliable vs. best effort
• connection-oriented vs. connectionless
 Once configured the application can
 pass data to the socket for network
transmission
 receive data from the socket (transmitted
through the network by some other host)
2
A Socket-eye view of the
Internet
medellin.cs.columbia.edu
(128.59.21.14)

newworld.cs.umass.edu
(128.119.245.93)

cluster.cs.columbia.edu
(128.59.21.14, 128.59.16.7,
128.59.16.5, 128.59.16.4)

 Each host machine has an IP address


 When a packet arrives at a host

3
Ports
 Each host has 65,536
Port 0
ports
Port 1
 Some ports are
reserved for specific
Port 65535
apps
 20,21: FTP
 A socket provides an interface
 23: Telnet to send data to/from the
 80: HTTP network through a port
 see RFC 1700 (about
2000 ports are
reserved)
4
Two essential types of sockets
 SOCK_STREAM  SOCK_DGRAM
 a.k.a. TCP  a.k.a. UDP
 reliable delivery  unreliable delivery
 in-order guaranteed  no order guarantees
 connection-oriented  no notion of “connection” –
 bidirectional app indicates dest. for each
packet
 can send or receive
App

3 2 App D1
1
socket Dest.
3 2
1
socket D2

D3
5
Simple Client-Server Example
response
Client Server
request
setup()
socket()
setup() bind()
socket() listen()
Connection
connect() establishment
accept()
send()
Data request recv()

Data response send()


recv()
close() recv()
End-of-file notification
CEN4500C close()
6
First thing first
 Use Header file:
 #include <winsock2.h>

 Link to library (ws2_32.lib) OR Add

7
Step-1: Initialing a socket
 int iResult = WSAStartup(
MAKEWORD(2,2),
&wsaData );
 Parameters
 Size of WSADATA
 A pointer to the WSADATA data structure

8
Step-1: Initialing a socket: Code
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2),
&wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");
else
printf("Client Sock API initiated...\n");

9
Step-2: Socket Creation in C:
 int s = socket(domain, type, protocol);
 s: socket descriptor, an integer (like a file-handle)
 domain: integer, communication domain
• e.g., PF_INET (IPv4 protocol) – typically used
 type: communication type
• SOCK_STREAM: reliable, 2-way, connection-based
service
• SOCK_DGRAM: unreliable, connectionless,
• other values: need root permission, rarely used, or
obsolete
 protocol: specifies protocol - usually set to 0
 NOTE: socket call does not specify where data will be
coming from, nor where it will be going to – it just
creates the interface!
10
Step-2: Socket Creation in C: Code
SOCKET m_socket;
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( m_socket == INVALID_SOCKET )
{
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
}
else
printf("Client Socket Created...\n”);

11
IP Address Data Structure
struct sockaddr_in {
short int sin_family; // Address family
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8];
};

struct in_addr {
unsigned long s_addr; // 4 bytes
};

12
bind():
bind() tells the OS to assign a local IP address and
local port number to the socket.
Many applications let the OS choose an IP address.
Use wildcard INADDR_ANY as local address in this case.
At server, user process must call bind() to assign a
port
At client, bind() is not required since OS may
assign available port and IP address
 The server will get the port number of the client through
the UDP/TCP packet header
Note: Each application is represented by a server
port number
CEN4500C
13
The bind function
 int status = bind(sockid, &addrport, size);
 status: error status, = -1 if bind failed
 sockid: integer, socket descriptor
 addrport: struct sockaddr, the (IP) address and port of the
machine (address usually set to INADDR_ANY – chooses a
local address)
 size: the size (in bytes) of the addrport structure

 bind can be skipped for both types of sockets.


When and why?

14
The bind Code
/* Bind socket 's' with socket detail object */

if ( bind( s, (SOCKADDR*) &sock_info, sizeof(sock_info) ) ==


SOCKET_ERROR )
{
printf( "bind() failed.\n" );
closesocket(s);
}
else
printf("Step-3:Server Socket is binded to port: 786 \n");

15
Skipping the bind
 SOCK_DGRAM:
 if only sending, no need to bind. The OS finds a
port each time the socket sends a pkt
 if receiving, need to bind

 SOCK_STREAM:
 destination determined during conn. setup
 don’t need to know port sending from (during
connection setup, receiving end is informed of
port)

16
Connection Setup (SOCK_STREAM)
 Recall: no connection setup for SOCK_DGRAM
 A connection occurs between two kinds of
participants
 passive: waits for an active participant to request
connection
 active: initiates connection request to passive side
 Once connection is established, passive and active
participants are “similar”
 both can send & receive data
 either can terminate the connection

17
connect(): Making TCP
Connection to Server
struct sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 786 );

if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) )


== SOCKET_ERROR)
{
printf( "Failed to connect.\n" );
WSACleanup();
getch();
return 0;
}
else
printf("Connected to server ...\n");

18
listen(): Wait for Connections
int listen(int sockfd, int backlog);

Puts socket in a listening state, willing to


handle incoming TCP connection request.
Backlog: number of TCP connections that can
be queued at the socket.

19
listen(): Wait for Connections
if ( listen( s, 1 ) == SOCKET_ERROR )
printf( "Error listening on socket.\n");
else
printf("Server Socket started listening...\n");
SOCKET AcceptSocket;
while (1)
{
AcceptSocket = SOCKET_ERROR;
while ( AcceptSocket == SOCKET_ERROR )
{
AcceptSocket = accept( s, NULL, NULL );
}
printf( "Client Connected.\n");
s = AcceptSocket;
break;
} 20
Sending / Receiving Data
 With a connection (SOCK_STREAM):
 int count = send(sock, &buf, len, flags);
• count: # bytes transmitted (-1 if error)
• buf: char[], buffer to be transmitted
• len: integer, length of buffer (in bytes) to transmit
• flags: integer, special options, usually just 0
 int count = recv(sock, &buf, len, flags);
• count: # bytes received (-1 if error)
• buf: void[], stores received bytes
• len: # bytes received
• flags: integer, special options, usually just 0
 Calls are blocking [returns only after data is sent
(to socket buf) / received]
21
send(): Sending Packets
printf("Plese Enter Word to Send: ");
char sendbuf[32];
scanf("%s",&sendbuf);
int bytesSent;
bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

Needs socket descriptor/object,


Buffer containing the message, and
Length of the message
Can also use write()

CEN4500C
22
recv(): Receive Packets

// Receive data.

char recvbuf[32] = "";


int bytesRecv = recv( s, recvbuf, 32, 0 );
printf( "Bytes Recv: %ld\n", bytesRecv );
printf("Message Recv: %s",recvbuf);

buffer_len

*bytes_read

23
Server Programming: Simple
Create stream socket (socket() )
Bind port to socket (bind() )
Listen for new client (listen() )
While
 accept user connection and create a new socket
(accept() )
 data arrives from client (recv() )
 data has to be send to client (send() )

24
Receiving Packets:
Separating Data in a Stream
Fixed length Fixed length
record record

A B C D

0 1 2 3 4 5 6 7 8 9

slide through
receive
buffer
Use records (data structures) to
partition the data stream
25
Connection setup cont’d
 Passive participant  Active participant
 step 1: listen (for
incoming requests)
 step 2: request &
 step 3: accept (a
establish connection
request)
 step 4: data transfer
 step 4: data transfer
 The accepted
connection is on a new Passive Participant
socket a-sock-1 l-sock a-sock-2
 The old socket
continues to listen for
other active
participants socket socket
Active 1 Active 2
26
Connection setup: listen & accept
 Called by passive participant
 int status = listen(sock, queuelen);
 status: 0 if listening, -1 if error
 sock: integer, socket descriptor
 queuelen: integer, # of active participants that can
“wait” for a connection
 listen is non-blocking: returns immediately

 int s = accept(sock, &name, &namelen);


 s: integer, the new socket (used for data-transfer)
 sock: integer, the orig. socket (being listened on)
 name: struct sockaddr, address of the active participant
 namelen: sizeof(name): value/result parameter
• must be set appropriately before call
• adjusted by OS upon return
 accept is blocking: waits for connection before returning
27
connect call
 int status = connect(sock, &name, namelen);
 status: 0 if successful connect, -1 otherwise
 sock: integer, socket to be used in connection
 name: struct sockaddr: address of passive
participant
 namelen: integer, sizeof(name)

 connect is blocking

28
close
 When finished using a socket, the socket
should be closed:
 status = close(s);
 status: 0 if successful, -1 if error
 s: the file descriptor (socket being closed)

 Closing a socket
 closes a connection (for SOCK_STREAM)
 frees up the port used by the socket

29
The struct sockaddr
 The generic:  The Internet-specific:
struct sockaddr { struct sockaddr_in {
u_short sa_family; short sin_family;
char sa_data[14]; u_short sin_port;
}; struct in_addr sin_addr;
char sin_zero[8];
};
 sa_family
 sin_family = AF_INET
• specifies which
 sin_port: port # (0-65535)
address family is
being used  sin_addr: IP-address

• determines how the  sin_zero: unused


remaining 14 bytes
are used

30
select function call
 int status = select(nfds, &readfds, &writefds,
&exceptfds, &timeout);
 status: # of ready objects, -1 if error
 nfds: 1 + largest file descriptor to check
 readfds: list of descriptors to check if read-ready
 writefds: list of descriptors to check if write-ready
 exceptfds: list of descriptors to check if an
exception is registered
 timeout: time after which select returns, even if
nothing ready - can be 0 or 
(point timeout parameter to NULL for )
31
Release of ports
 Sometimes, a “rough” exit from a program (e.g.,
ctrl-c) does not properly free up a port
 Eventually (after a few minutes), the port will be
freed
 To reduce the likelihood of this problem, include
the following code:
#include <signal.h>
void cleanExit(){exit(0);}
 in socket code:
signal(SIGTERM, cleanExit);
signal(SIGINT, cleanExit);

32
Final Thoughts
?

33

Potrebbero piacerti anche