I have two machines, that I would like both of them to communicate using sockets under C programming language.
I have developed two samples to represent both sides but I noticed that I can send data successfully if they are smaller than certain number.
The size that I have tested but does not work is sending & receiving 2048 bytes , on contrary, for other smaller sizes such as 258 Bytes, 1KByte it works fine.
After doing some investigations, I found out that, the sending operation has no errors while for the reception, I did not get any thing at all.
I have checked the sending and receiving buffer sizes on both machines and I guess they are sufficient.
Here are the first side of my code:
/* UDP client in the internet domain */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#define BUFF_SIZE 1800
#define MOBIPASS_L2_IP_ADDRESS "192.168.13.53"
#define MOBIPASS_L2_PORT_NUM 12001
#define BRIDGE_IP_ADDRESS "192.168.13.30"
#define BRIDGE_PORT_NUM 12000
#define RESTRICT_SRC_DST_NUM 1
#define TEN_MSEC 10000
void error(const char *);
void adjustSockParam (int sockFD);
int main(int argc, char *argv[])
{
#if RESTRICT_SRC_DST_NUM
int bridge_sock_fd = -1, n =-1;
struct sockaddr_in server_mobipass, client_bridge;
char buffer[BUFF_SIZE];
char* choice = NULL;
size_t size = 1;
/* create socket descriptor at client machine*/
bridge_sock_fd= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (bridge_sock_fd < 0) error("socket");
/* *********************************************************
* prepare source information of the socket file descriptor
* *********************************************************
*/
client_bridge.sin_family = AF_INET;
client_bridge.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS) ;
client_bridge.sin_port = htons(BRIDGE_PORT_NUM);
if( bind( bridge_sock_fd, (struct sockaddr *) &client_bridge, sizeof ( client_bridge ) ) < 0 )
{
error( "bind" );
}
/* *********************************************************
* prepare destination information of the socket file descriptor
* *********************************************************
*/
server_mobipass.sin_family = AF_INET;
server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ;
server_mobipass.sin_port = htons(MOBIPASS_L2_PORT_NUM);
if( connect( bridge_sock_fd, (struct sockaddr *) &server_mobipass, sizeof ( server_mobipass ) ) < 0 ) {
error("connect");
}
adjustSockParam(bridge_sock_fd);
do
{
printf("sending traffic?[y/n]\n");
getline(&choice,&size,stdin);
if(*choice=='n')
break;
strncpy( buffer,
"Hello Mobipass, this is bridge :)\n",
sizeof(buffer));
n = send( bridge_sock_fd, buffer, sizeof(buffer), MSG_CONFIRM );
if( n < 0 )
{
error( "send" );
}
assert(n == sizeof(buffer));
usleep(TEN_MSEC);
/*memset(buffer,0 , sizeof(buffer));
if( recv( bridge_sock_fd, buffer, sizeof(buffer), 0 ) < 0 )
{
error( "recv" );
}
else
{
printf("Msg received from mobipass is:\n%s",buffer);
}*/
}while(*choice == 'y' || *choice == 'Y');
close( bridge_sock_fd );
#else
int tx_sock, n, rx_sock;
unsigned int srv_length;
struct sockaddr_in server_mobipass, from, server_bridge;
char buffer[256];
/* create socket descriptor at client machine*/
tx_sock= socket(AF_INET, SOCK_DGRAM, 0);
if (tx_sock < 0) error("socket");
srv_length=sizeof(struct sockaddr_in);
/*prepare server (peer entity) of UDP connection*/
server_mobipass.sin_family = AF_INET;
server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ;
server_mobipass.sin_port = htons(MOBIPASS_L2_PORT_NUM);
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n=sendto(tx_sock,buffer,
strlen(buffer),0,(const struct sockaddr *)&server_mobipass,srv_length);
if (n < 0) error("Sendto");
rx_sock= socket(AF_INET, SOCK_DGRAM, 0);
if (rx_sock < 0) error("socket");
server_bridge.sin_family = AF_INET;
server_bridge.sin_addr.s_addr = inet_addr(BRIDGE_IP_ADDRESS);
server_bridge.sin_port = htons(BRIDGE_PORT_NUM);
if (bind(rx_sock,(struct sockaddr *)&server_bridge,srv_length)<0)
error("binding");
n = recvfrom(rx_sock,buffer,256,0,(struct sockaddr *)&from, &srv_length);
if (n < 0) error("recvfrom");
/*print to stdout what have been received*/
write(1,"Got an ack: ",12);
write(1,buffer,n);
/* close sockets */
close(rx_sock);
close(tx_sock);
#endif /* RESTRICT_SRC_DST_NUM */
return 0;
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
void adjustSockParam (int sockFD)
{
int option_value;
socklen_t option_len = sizeof(option_value);
/** Adjust Send Buffer Size**/
if( getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Initial SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);
/*option_value = 2048;
if( setsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, option_len)< 0)
{
error("get Socket Option error:");
}
if( getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Final SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);*/
/** Adjust Receiver Buffer Size **/
if( getsockopt(sockFD, SOL_SOCKET, SO_RCVBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Initial SO_RCVBUF: option_len = %d option_value = %d\n",option_len,option_value);
}
Here are the second side of my code:
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include <assert.h>
#define BUFF_SIZE 1800
#define MOBIPASS_L2_IP_ADDRESS "192.168.13.53"
#define MOBIPASS_L2_PORT_NUM 12001
#define BRIDGE_IP_ADDRESS "192.168.13.30"
#define BRIDGE_PORT_NUM 12000
#define DUMP 0
#define ACT_AS_STRING 0
#define RESTRICT_SRC_DST_NUM 1
#define TEN_MSEC 10000
#if DUMP
#define DUMP_BUFFER(buf,len) \
{ \
int i; \
for(i = 0; i < len; i++) \
printf("buf[%d] = 0x%x",i,buf[i]); \
}
#else
#define DUMP_BUFFER(buf,len) printf("received len=%d\n",len)
#endif
void adjustSockParam (int sockFD);
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
#if RESTRICT_SRC_DST_NUM
int mobipass_sock_fd = -1;
struct sockaddr_in server_mobipass, client_bridge;
char buffer[BUFF_SIZE];
int recivedBytes=-1;
printf("size of buffer = %d\n",sizeof(buffer));
/* create socket descriptor at client machine*/
mobipass_sock_fd= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (mobipass_sock_fd < 0) error("socket");
/* *********************************************************
* prepare source information of the socket file descriptor
* *********************************************************
*/
client_bridge.sin_family = AF_INET;
client_bridge.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ;
client_bridge.sin_port = htons(MOBIPASS_L2_PORT_NUM);
if( bind( mobipass_sock_fd, (struct sockaddr *) &client_bridge, sizeof ( client_bridge ) ) < 0 )
{
error( "bind" );
}
/* *********************************************************
* prepare destination information of the socket file descriptor
* *********************************************************
*/
server_mobipass.sin_family = AF_INET;
server_mobipass.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS) ;
server_mobipass.sin_port = htons(BRIDGE_PORT_NUM);
if( connect( mobipass_sock_fd, (struct sockaddr *) &server_mobipass, sizeof ( server_mobipass ) ) < 0 ) {
error("connect");
}
adjustSockParam(mobipass_sock_fd);
printf("waiting for message from bridge:\n");
do{
memset(buffer,0 , sizeof(buffer));
recivedBytes = recv( mobipass_sock_fd, buffer, sizeof(buffer), 0 );
if( recivedBytes < 0 )
{
error( "recv" );
}
else
{
assert(recivedBytes == sizeof(buffer));
DUMP_BUFFER(buffer,recivedBytes);
#if ACT_AS_STRING
printf("Msg received from bridge is:\n%s",buffer);
#endif
}
usleep(TEN_MSEC);
#if ACT_AS_STRING
strncpy( buffer,
"Hello Bridge, this is mobipass :)\n",
sizeof(buffer));
if( send( mobipass_sock_fd, buffer, sizeof(buffer), 0 ) < 0 )
{
error( "send" );
}
#endif
}while(1);
close( mobipass_sock_fd );
#else
int tx_sock, n, rx_sock;
unsigned int srv_length;
socklen_t fromlen;
struct sockaddr_in server_mobipass, from, server_bridge;
char buf[1024];
rx_sock=socket(AF_INET, SOCK_DGRAM, 0);
if (rx_sock < 0) error("Opening socket");
else printf("Creating rx udp socket\n");
srv_length = sizeof(server_mobipass);
bzero(&server_mobipass,srv_length);
server_mobipass.sin_family=AF_INET;
server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS);
server_mobipass.sin_port=htons(MOBIPASS_L2_PORT_NUM);
if (bind(rx_sock,(struct sockaddr *)&server_mobipass,srv_length)<0)
error("binding");
else
printf("Binding a socket to a server IP address\n");
fromlen = sizeof(struct sockaddr_in);
tx_sock=socket(AF_INET, SOCK_DGRAM, 0);
if (tx_sock < 0) error("Opening socket");
else printf("Creating tx udp socket\n");
server_bridge.sin_family=AF_INET;
server_bridge.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS);
server_bridge.sin_port=htons(BRIDGE_PORT_NUM);
while (1)
{
printf("waiting for a message from client side:\n");
n = recvfrom(rx_sock,buf,1024,0,(struct sockaddr *)&from,&fromlen);
if (n < 0) error("recvfrom");
write(1,"Message received from eNB machince:\n",36);
write(1,buf,n);
n = sendto(tx_sock,"hello eNB, I am mobipass\n",27,
0,(struct sockaddr *)&server_bridge,fromlen);
if (n < 0) error("sendto");
}
#endif
return 0;
}
void adjustSockParam (int sockFD)
{
int option_value;
socklen_t option_len = sizeof(option_value);
/** Adjust Send Buffer Size**/
if( getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Initial SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);
/* option_value = 2048;
if( setsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, option_len)< 0)
{
error("get Socket Option error:");
}
if( getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Final SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);*/
/** Adjust Receiver Buffer Size **/
if( getsockopt(sockFD, SOL_SOCKET, SO_RCVBUF,
&option_value, &option_len)< 0)
{
error("get Socket Option error:");
}
printf("Initial SO_RCVBUF: option_len = %d option_value = %d\n",option_len,option_value);
}
Here is the output on first side:
Initial SO_SNDBUF: option_len = 4 option_value = 112640
Initial SO_RCVBUF: option_len = 4 option_value = 112640
sending traffic?[y/n]
y
sending traffic?[y/n]
y
Here is the output on second side:
size of buffer = 1800
Initial SO_SNDBUF: option_len = 4 option_value = 1048576
Initial SO_RCVBUF: option_len = 4 option_value = 1048576
waiting for message from bridge:
I am not sure what I am doing wrong here. Do you any suggestions?
While UDP datagram packet size could be up to 64K (16-bit data length field), the usual underlying data link technology - ethernet - has a frame size of 1500 bytes. Less at least 20 bytes for IP header, less 8 bytes of UDP header, that leaves only 1472 bytes for UDP payload that could be sent without IP fragmentation, which usually leads to issues like in your case where packets are just dropped somewhere.
Most UDP-based protocols restrict datagram size for exactly this reason.
Related
I am trying to create a small program that takes a http requests through stdin and sends it to a server.
This is the code I am using:
int portno = 3000;
char *message = buf;
char response[4096];
int byte_count;
fsize = strlen(message);
int sockfd;
/* fill in the parameters */
printf("Request:\n%s\n",message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
int sz = (1024 * 1024);
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz)) == -1) {
perror("setsockopt");
exit(1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(portno);
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(sockfd, &saddr, sizeof(saddr)) == -1) {
perror("connect");
}
send(sockfd, message, fsize, MSG_NOSIGNAL);
printf("written");
byte_count = recv(sockfd,response,sizeof(response)-1,0); // <-- -1 to leave room for a null terminator
response[byte_count] = 0; // <-- add the null terminator
printf("recv()'d %d bytes of data in buf\n",byte_count);
printf("%s",response);
close(sockfd);
buf is equal to this
GET /alias%2Findex.html HTTP/1.0\r\n
\r\n
\r\n
\r\n
I have done some research through other stack overflow posts and they state that recv usually hangs when the system is waiting for a response. I do not know what could be causing this.
Here is your program only slightly modified. And it works for me.
Are you certain whatever server you are running on localhost port 3000 is responding properly? BTW, I had to change the port to 8080 for my system.
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
char buf[1 << 16] = "GET /file.txt HTTP/1.0\r\n"
"\r\n"
"\r\n";
int main() {
int portno = 8080;
char *message = buf;
int byte_count;
int fsize = strlen(message);
int sockfd;
/* fill in the parameters */
printf("Request:\n%s\n", message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
perror("ERROR opening socket");
int sz = (1024 * 1024);
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz)) == -1) {
perror("setsockopt");
exit(1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(portno);
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
perror("connect");
}
send(sockfd, message, fsize, MSG_NOSIGNAL);
printf("written");
while ((byte_count = recv(sockfd, buf, sizeof(buf) - 1, 0)) >
0) { // <-- -1 to leave room for a null terminator
buf[byte_count] = 0; // <-- add the null terminator
printf("recv()'d %d bytes of data in buf\n", byte_count);
printf("%s", buf);
}
close(sockfd);
return 0;
}
I'm trying to transmit from the client side a wav file through socket (UDP) and have the server playing the wav file by means of the ALSA library.
Since my coding level in C is very low I've first learnt how to set up a communication between client and server via sockets and interchange text messages.
Afterwards I've learnt how to play a wav file with ALSA by redirecting the stdin when running the playback app.
I've tried to joint both code (UDPServer.c + playback.c) files and when I pass the stdin to the UDPClient.c file it sends it to the UDPServer.c but it's just a pure tone instead of the actual music file that I'm trying to pass.
I don't know how exactly to pass the file into the UDPClient.c in order for it to send it to the socket to the server.
UDPServer.c
// Server side implementation of UDP client-server model
// Libraries
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <alsa/asoundlib.h>
// CONSTANTS
#define PORT 8080
#define MAXLINE 2048
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
// FUNCTION DECLARATION
int audio_play (char signal);
// Main code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "AUDIO PLAYBACK FINISH";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/result
// Receive a mesage from the socket
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);
buffer[n] = '\0';
//printf("Client : %s\n", buffer);
audio_play(buffer);
// Send a message on the socket
sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);
printf("PLAYING AUDIO???.\n");
return 0;
}
// FUNCTIONS
int audio_play (char s)
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* 48000 bits/second sampling rate */
val = 48000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 32 frames. */
frames = 32;
snd_ pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 4; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params, &val, &dir);
/* 5 seconds in microseconds divided by
* period time */
loops = 5000000 / val;
while (loops > 0) {
loops--;
// rc = read(0, buffer, size);
rc = s;
if (rc == 0) {
fprintf(stderr, "end of file on input\n");
break;
} else if (rc != size) {
fprintf(stderr, "short read: read %d bytes\n", rc);
}
rc = snd_pcm_writei(handle, buffer, frames);
if (rc == -EPIPE) {
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr, "error from writei: %s\n", snd_strerror(rc));
} else if (rc != (int)frames) {
fprintf(stderr, "short write, write %d frames\n", rc);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
}
UDPClient.c
// Client side implementation of UDP client-server model
// Libraries
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
// CONSTANTS
#define PORT 8080
#define MAXLINE 2048
// Main code
int main(int argc, char **argv) {
int sockfd;
char buffer[MAXLINE];
char *data = "Here is where the file of audio should be?";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
int n, len;
// Send a message on the socket
sendto(sockfd, (const char *)data, strlen(data), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("AUDIO SENT.\n");
// Receive a message from the socket
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
close(sockfd);
return 0;
}
I am currently trying to create a multiple client-server which enables server to perform both read and write functions in C language. I am able to read the data from the client using readfds and putting it as parameter in SELECT. When I added in writefds, the client fails to connect to the server. I am not sure what is the issue behind it, whether this is the correct method to transmit and receive data
This is the code for my server
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> //close
#include <arpa/inet.h> //close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros
#define TRUE 1
#define FALSE 0
#define PORT 8080
int main(int argc , char *argv[])
{
int opt = TRUE;
int master_socket , addrlen , new_socket , client_socket[30] ,
max_clients = 2 , activity, i , valread , sd;
int max_sd;
struct sockaddr_in address;
char buffer[1025]; //data buffer of 1K
fd_set readfds;
fd_set writefds;
char *message = "Welcome to Server\r\n";
//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
//client_socket[i] = 0;
}
//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//type of socket created
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
//bind the socket to localhost port 8888
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Listener on port %d \n", PORT);
if (listen(master_socket, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
addrlen = sizeof(address);
puts("Waiting for connections ...");
for(;;)
{
//clear the socket set
FD_ZERO(&readfds);
FD_ZERO(&writefds);
//add master socket to set
FD_SET(master_socket, &readfds);
FD_SET(master_socket, &writefds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_clients ; i++)
{
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);
//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
activity = select( max_sd + 1 , &readfds , &writefds, NULL , NULL);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket,
(struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
else {
printf("Connected to socket \n");
}
bzero(buffer, 1025);
int n=0;
read(new_socket, buffer, sizeof(buffer));
printf("From client: %s\t To client: ", buffer);
bzero(buffer, 1025);
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets as %d\n" , i+1);
}
}
}
else if(FD_ISSET(master_socket, &readfds)) {
printf("From client: %s\t To client : ", buffer);
bzero(buffer, 1025);
// copy server message in the buffer
while ((buffer[n++] = getchar()) != '\n')
;
write(new_socket, buffer, sizeof(buffer));
}
else{
//else its some IO operation on some other socket
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];
if (FD_ISSET( sd , &readfds))
{
//Check if it was for closing , and also read the
//incoming message
if ((valread = read( sd , buffer, 1024)) == 0)
{
close( sd );
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
}
}
}
}//else
}
return 0;
}
This is the code for the client
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#define MAX 1000
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
int n;
int firstConnect = 1;
for (;;)
{
bzero(buff, sizeof(buff));
n = 0;
if(firstConnect==1) {
printf("Enter the string : ");
firstConnect = 0;
while ((buff[n++] = getchar()) != '\n')
;
write(sockfd, buff, sizeof(buff));
}
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server: %s\t To Server : ", buff);
while ((buff[n++] = getchar()) != '\n');
write(sockfd, buff, sizeof(buff));
if ((strncmp(buff, "exit", 4)) == 0)
{
printf("Client Exit...\n");
break;
}
}
}
int main()
{
printf("CLIENT");
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
// servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_addr.s_addr = inet_addr("127.8.1.0");
servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0)
{
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
func(sockfd);
// close the socket
close(sockfd);
}
As side node, it appears that you expect read to zero-terminate received data. That is not the case. The length of received data is in the return value of read, it must not be ignored.
It also appears that you expect write to find the end of the string you are sending. That doesn't happen. You must specify the exact length of the data you are sending, rather than the length of the buffer that contains the data.
send/write and recv/read functions work on binary data rather than zero-terminated strings and can send/receive less than the specified size or may return an error. Learn how to use these functions correctly by not ignoring the return value and handling errors and partial reads and writes.
I met a strange problem when I test my server and client.
The server and client appear TIME_WAIT at the same time!
Here is my server code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h> //bzero
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LISTEN_QUEUE 20
#define MAX_LINE 1024
#define MAXN 16384
int parse(char *buf)
{
int num;
sscanf(buf, "%d", &num);
return num;
}
int main()
{
int listenfd, connfd, r, n;
pid_t childpid;
socklen_t chilen;
struct sockaddr_in chiaddr, servaddr;
char buf[MAX_LINE];
char content[MAXN];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0)
printf("listen socket get error\n"), exit(-1);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9999);
r = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if(r < 0)
printf("bind socket error\n"), exit(-1);
r = listen(listenfd, LISTEN_QUEUE);
memset(content, 'A', MAXN);
while(1)
{
chilen = sizeof(chiaddr);
connfd = accept(listenfd, (struct sockaddr *)&chiaddr, &chilen);
memset(buf, 0, MAX_LINE);
r = read(connfd, buf, MAX_LINE);
n = parse(buf);
write(connfd, content, n);
close(connfd);
}
}
And here is my client code:
#include <unp.h>
#define MAXN 16384
static int readn(int fd, char *buf, int nbytes)
{
int nread, ntoread, n;
#ifdef __DEBUG__
char temp[1024];
#endif /* __DEBUG__ */
nread = 0;
ntoread = nbytes;
while(nread < nbytes)
{
n = read(fd, buf, ntoread);
if(n < 0)
printf("read nbytes error\n"), exit (-1);
else if(n == 0)
break;
else
{
#ifdef __DEBUG__
memcpy(temp, buf, n);
temp[n] = 0;
printf("%s\n", temp);
#endif /* _DEBUG__ */
buf += n;
nread += n;
ntoread = nbytes - nread;
}
}
return nread;
}
static int Tcp_connect(char *host, char *port)
{
struct hostent *h;
char str[16];
struct sockaddr_in addr;
h = gethostbyname(host);
addr.sin_family = h->h_addrtype;
addr.sin_port = htons(atoi(port));
addr.sin_addr = *(struct in_addr *)(h->h_addr);
#ifdef __DEBUG__
if(h->h_addrtype == AF_INET)
printf("AF_INET\n");
printf("server ip is :%s\n", inet_ntoa(addr.sin_addr));
#endif /* __DEBUG__ */
int fd = socket(h->h_addrtype, SOCK_STREAM, 0);
if(fd < 0)
printf("socket get failed\n"), exit(-1);
#ifdef __DEBUG__
printf("socket get success\n");
#endif /* __DEBUG__ */
if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
printf("connect failed\n"), exit(-1);
#ifdef __DEBUG__
printf("connected success\n");
#endif /* __DEBUG__ */
return fd;
}
int main(char argc, char *argv[])
{
int i, j, fd, nchilds, nloops, nbytes;
pid_t pid;
ssize_t n, nread;
char request[MAX_LINE], reply[MAXN];
if(argc != 6)
printf("usage : client <IP addr> <port> <#children>
<#loops/child> <#bytes/request>"),
exit(-1);
nchilds = atoi(argv[3]);
nloops = atoi(argv[4]);
nbytes = atoi(argv[5]);
snprintf(request, sizeof(request), "%d\n", nbytes);
for(i = 0; i < nchilds; i++)
{
if((pid = fork()) == 0) //son
{
nread = 0;
for(j = 0; j < nloops; j++)
{
// printf("begin connect\n");
fd = Tcp_connect(argv[1], argv[2]);
write(fd, request, strlen(request));
if((n = readn(fd, reply, nbytes)) != nbytes)
printf("server return %d bytes\n", (int)n), exit(-1);
else
nread += n;
close(fd);
}
printf("child %d done, read total %d bytes\n", i, (int)nread);
exit(0);
}
}
while(wait(NULL) > 0) ;
if(errno != ECHILD)
printf("wait error\n"), exit(-1);
}
I run server and client on my machine.
And the client cmd is
./client 127.0.0.1 9999 5 100 4000
and then I run
netstat -a | grep 9999 > log
when I run
grep -c TIME_WAIT log
the result is 501, but according to book, the result should be 500.
I open the log, then I find server and client in TIME_WAIT at the same time on one connection
tcp 0 0 localhost:54915 localhost:9999 TIME_WAIT
tcp 0 0 localhost:9999 localhost:54915 TIME_WAIT
It is so strange, I don't know why
You are establishing and closing connection between client and server in loop - client connects to server, sends some data, receives response from server and then closes the connection. Similarly the server also disconnects after this exchange. You are observing TIME_WAIT state as you are closing connections between client and server.
The TIME_WAIT state is a normal TCP connection state, as the TCP stack does not immediately wipe out the TCBs after FIN exchange. The TIME_WAIT state represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. Please refer to TCP RFC 793 for more details on TCP state machine.
If you do a grep on port 9999, you will notice connection in ESTABLISHED state while your client and server are running.
Possibly you can avoid establishing and closing TCP connection in loop, that is, change your server and client programs to establish connection and then enter the loop for exchanging data.
I am trying to write client/server program in c.
I am getting connection refused. I am not able to figure out what is the problem
Can anyone please help me.
This is the server
// include directories
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "strings.h"
#include "arpa/inet.h"
#include "math.h"
#define PORTNUM 1300
#define LISTENQ 10
#define BUFFER 1024
int main( int argc, char *argv[] )
{
int i, maxi, maxfd, listenfd, connfd, sockfd, flag, previousfd;
int nready, client[FD_SETSIZE];
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
fd_set rset, allset;
ssize_t n;
struct frame fpart, bufferedPart1,bufferedPart2 ;
char recvline[BUFFER], sendline[BUFFER];
/* First call to socket() function */
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket Error");
exit(-1);
}
printf("I ma here");
/* Initialize socket structure */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5000);
servaddr.sin_addr.s_addr = INADDR_ANY;
/* Now bind the host address using bind() call.*/
if((bind(sockfd,(struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)))== -1)
{
perror("Bind Error");
exit(-1);
}
printf("I ma here");
/* Now start listening for the clients */
listen(listenfd, LISTENQ);
printf("I ma here");
flag = 0;
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) {
/* new client connection */
clilen = sizeof(cliaddr);
printf("I ma here");
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
perror("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) {
/* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = read(sockfd, recvline, sizeof(recvline))) == 0) {
/* connection closed by client */
close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} }
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
The server should be able to listen to more than one client. So I used select.
According to man 2 listen, the first argument should be the file descriptor of the socket that should be listened for connections.
In your server's code, listenfd is uninitialized. What you actually need to listen(2) on, is the socket with file descriptorsockfd.
Initialize listenfd as sockfd just before calling listen(2), or replace listenfd with sockfd on server's side, and it should work.
In addition, have a look at this question about when to use "..." and <...> in #include statement.