TCP multi-user chatserver in C - c

I am trying to build up a multiuser chatserver in C and have a problem catching the users pseudonym. The first message from the user should be used as his pseudonym.
I'm testing my server with telnet, but everytime when I connect its sending an unreadable message to the server and the server is not waiting for the first message from the client.
if (FD_ISSET(sock, &readfds)) {
SOCKADDR_IN csin = {0};
size_t sinsize = sizeof(csin);
int clientsocket = accept(sock, (SOCKADDR *) &csin, (socklen_t *restrict) &sinsize);
if (clientsocket == -1) {
printf("Verbindung konnte nicht angenommen werden\n");
continue;
} else
{
printf("Verbindung angenommen\n");
}
//get clients username
recv(clientsocket, buffer, BUFFER_SIZE - 1, 0);
max = clientsocket > max ? clientsocket : max;
FD_SET(clientsocket, &readfds);
Client c;
c.sock = clientsocket;
strncpy(c.name, buffer, BUFFER_SIZE - 1); //store username in c.name
printf(c.name);
clients[actual] = c;
actual ++;
}
Whats the problem there? Thanks for help

Related

How to send data from python to C using sockets (unix)

I'm trying to create a unix socket to allow some of my c code to talk to some of my python code. The C code is acting as the socket and the python as the client. So far I have been able to create the socket and connect the client to it, but i'm either unable to send data through it or receive data through it in either direction (I can't tell where the problem is).
I've tried changing the encoding of the data i'm sending, I've tried sending the data over and over again in case it's a timing issue, these don't appear to be the problem.
C server code:
int makeSocket(struct sockaddr_un * addr, char* path){
unlink(path);
int sock;
//struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, path, sizeof(addr->sun_path));
size_t size = (offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path));
if (bind(sock, (struct sockaddr*) addr, size) < 0){
printf("failed to bind\n");
}
listen(sock, 5);
return sock;
}
//this isn't actually here but just so you can see it being created, its a global int
globSock = makeSocket("socket.soc");
Then in an idle callback:
f (!connected){
int len = sizeof(addr);
if (connection = accept(globSock, (struct sockaddr*) &addr, &len) < 0){
printf("Can't listen\n");
} else {
printf("connected\n");
send(connection, "HI", strlen("HI"), 0);
connected = 1;
}
} else {
int rc;
if (!recevd && ((rc = recv(connection,buffer,BUFFERSIZE,0)) < 0)){
printf("nope %s\n", buffer);
} else if (rc == 0) {
connected = 0;
printf("%s\n", buffer);
} else {
recevd = 1;
printf("%s\n", buffer);
}
}
connected and recevd are flag variables and buffer is an array of char (buffer size is 100, just a #define)
Python client:
# -*- coding: utf-8 -*-
import socket
import os
print("Connecting...")
if os.path.exists("socket.soc"):
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect("socket.soc")
print("Ready.")
print("Ctrl-C to quit.")
print("Sending 'DONE' shuts down the server and quits.")
while True:
try:
x = input("> ")
if "" != x:
print("SEND:", x)
client.send(x.encode('utf-8'))
if "DONE" == x:
print("Shutting down.")
break
except KeyboardInterrupt as k:
print("Shutting down.")
client.close()
break
else:
print("Couldn't Connect!")
print("Done")
On the C side it repeatedly prints "nope" (the I haven't received anything yet print) and on the python side it simply asks for input, you can give it the message, it'll 'send' it and then ask for another etc...
The issue was in
if (connection = accept(globSock, (struct sockaddr*) &addr, &len) < 0){
it was saving the comparison in connection rather than the actual socket the solution was:
if ((connection = accept(globSock, (struct sockaddr*) &addr, &len)) < 0){

Read blocks when no data are available to read from socket

I am implementing a server/client app for educational purposes. My server opens a socket and polls it for connections. If a connection is available it accepts it and sends some data over. Then it waits for input and sends some data back again.
When implementing the client side, I tried writing to the socket right away, but that did not work. I had to receive first what the server told me and then send it some data. Then wait to receive again.
This does not seem a good solution and since this is an educational project I was wondering how I would go about making it abstract (i.e. not care about how many times the server would send me something and I would send it something back.)
So far I have tried looping to receive the server's input but without success. The server writes twice to the socket, so the client must read twice before trying to send its own message. If I read a third time the read blocks (which I think is the normal behaviour).
I tried using poll on the socket from the client's side to watch for POLLOUT events, but it does not seem to work.
int connect(){
unsigned int backlog = 10;
/*
struct sockaddr_in {
short sin_family; // e.g. AF_INET
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
struct in_addr {
unsigned long s_addr; // load with inet_aton()
};
*/
struct sockaddr_in server{};
//Create socket
listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listeningSocket == -1) {
spdlog::critical("Could not create socket");
}
spdlog::debug("Socket created.");
//Prepare the socket for incoming connections
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PortNumber); // NOLINT(hicpp-signed-bitwise)
if (bind(listeningSocket, (const struct sockaddr *) &server, sizeof(sockaddr_in)) < 0) {
spdlog::critical("bind failed. Error");
exit(-1);
}
spdlog::debug("Bind succeeded\n");
if (!listen(listeningSocket, static_cast<int>(backlog))) {
return listeningSocket;
}
return -1;
}
Handle the message
void* sendMessage(){
//Get the socket descriptor
int sock = socket;
int read_size;
const char *message;
char client_message[200];
//Send some messages to the client
message = "Greetings! I am your connection handler\n";
write(sock, message, strlen(message));
message = "Now type something and i shall apply the caesar cipher to it \n";
write(sock, message, strlen(message));
//Receive a message from client
while ((read_size = recv(sock, client_message, 200, 0)) > 0) {
//end of string marker
client_message[read_size] = '\0';
std::string temp(client_message);
temp = cipher->operate(temp);
//Send the message back to client
write(sock, temp.c_str(), strlen(temp.c_str()));
//clear the message buffer
memset(client_message, 0, 200);
}
if (read_size == 0) {
spdlog::debug("Client disconnected");
fflush(stdout);
} else if (read_size == -1) {
spdlog::error("recv failed: {}",errno);
}
return nullptr;
}
As for the client side:
//Connect to the server
void connect()
{
struct hostent *he;
struct sockaddr_in their_addr{}; /* connector's address information */
if ((he=gethostbyname(mHost.c_str())) == nullptr) { /* get the host info */
spdlog::error("gethostbyname");
}
if ((mSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
spdlog::error("socket");
exit(1);
}
their_addr.sin_family = AF_INET; /* host byte order */
their_addr.sin_port = htons(mPort); /* short, network byte order */ //NOLINT
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */
if (connect(mSocket, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
spdlog::error("connect");
exit(1);
}
}
}
And try to send the message:
void sendMessage(){
#define MAX 100
if (!sockfd) {
sockfd = mSocket;
spdlog::info("Setting socket to {}", sockfd);
}
char buff[MAX];
struct pollfd fds[1];
fds[0].fd=sockfd;
while (( recv(sockfd, buff, 200, 0)) > 0) {
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
}
strcpy(buff, "PAPARI");
write(sockfd, buff, sizeof(buff));
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server : %s", buff);
close(sockfd);
}
This will block after the two messages from the server are received by the client.

C socket: recv and send simultaneously

I am trying to make a client server chat application with a single server and multiple client scenario. My server is working but I cant get the client working. I am using select() function to select whether I should recv() or send(). Here is my code for client implementation.
main()
{
int sockfd;
struct sockaddr_in serv_addr;
int i, sent;
char buf[100];
char buff[100];
/*
Opening a socket
Check whether opening is successful or not
*/
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("Unable to create socket\n");
}
printf("Socket created\n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(6000);
/*
Establish a connection with the server process
*/
if((connect(sockfd, (struct socketaddr *)&serv_addr, sizeof(serv_addr)))<0){
printf("Unable to connect to server\n");
exit(0);
}
printf("Client connected\n");
while(1){
for(i=0; i<100; i++){
buf[i] = '\0';
buff[i] = '\0';
}
fd_set rfd, wfd;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO( &rfd);
FD_ZERO( &wfd);
FD_SET( sockfd, &rfd);
//FD_SET( sockfd, &wfd);
FD_SET( 0, &wfd);
if( (select( sockfd + 1, &rfd, &wfd, NULL, &tv) < 0)) {
printf(" Select error \n");
exit(0);
}
if( FD_ISSET( sockfd, &rfd)) { // we got data ... need to read it
recv(sockfd, buff, 100, 0);
printf("Received result from server = %s\n",buff);
}
if( FD_ISSET( 0, &wfd)) {
fflush(stdin);
printf(">");
gets(buf);
sent = send(sockfd, buf, strlen(buf) + 1, 0);
printf("-------------Sent %d bytes to server--------------\n", sent);
}
}
printf("----------------Closing client------------------ \n");
close(sockfd);
}
Each client should get the message sent by one client to the server just like a chat application.
The problem is that you check if you can write to the standard input file descriptor. That makes no sense, you should check if you can read from it.
That is, you should add STDIN_FILENO to the read set too, and not have a write set at all.
I've got the same issue some days ago, but in c++. My problems were solved using these links:
http://easy-tutorials.net/c/multithreaded-socket-server-cpp/#comment-1024
http://easy-tutorials.net/c/linux-c-socket-programming/#creating_a_server
Probably you can adapt to your situation, this socket server make a broadcast as you want. Try compile it and you will see how it is works.
If you need some help, do not hesitate to ask.

Asynchronous C client for a multiclient C server

I have a client which is working fine, but whenever I run a new client, sometimes I don't receive the sent message on the other client already running, while using telnet it works flawlessly, the message "broadcasts" to all connected clients, and I want whenever a message is received to one of the clients to show even if I didn't already send a message.
Should I use select on clients ? and what should be changed ?
client.c:
#include <stdio.h> //printf
#include <string.h> //strlen
#include <sys/socket.h> //socket
#include <arpa/inet.h> //inet_addr
#include <unistd.h>
int main(int argc , char *argv[]){
int sock;
struct sockaddr_in server;
char message[256] , server_reply[256];
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 9034 );
//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0){
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
//keep communicating with server
for(;;){
printf("Enter message: ");
memset(message, 0, 256);
fgets(message, 256,stdin);
// scanf("%s" , message);
//Send some data
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
//Receive a reply from the server
if( recv(sock , server_reply , 256 , 0) < 0)
{
puts("recv failed");
break;
}
printf("Server Reply: %s\n", server_reply);
server_reply[0]='\0';
}
close(sock);
return 0;
}
server.c:
/*
** selectserver.c -- a cheezy multiperson chat server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define PORT "9034" // port we're listening on
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void){
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
int fdmax; // maximum file descriptor number
int listener; // listening socket descriptor
int newfd; // newly accept()ed socket descriptor
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
char buf[256]; // buffer for client data
int nbytes;
char remoteIP[INET6_ADDRSTRLEN];
int yes=1; // for setsockopt() SO_REUSEADDR, below
int i, j, rv;
struct addrinfo hints, *ai, *p;
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
// get us a socket and bind it
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0) {
fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
exit(1);
}
for(p = ai; p != NULL; p = p->ai_next) {
listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (listener < 0) {
continue;
}
// lose the pesky "address already in use" error message
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
close(listener);
continue;
}
break;
}
// if we got here, it means we didn't get bound
if (p == NULL) {
fprintf(stderr, "selectserver: failed to bind\n");
exit(2);
}
freeaddrinfo(ai); // all done with this
// listen
if (listen(listener, 10) == -1) {
perror("listen");
exit(3);
}
// add the listener to the master set
FD_SET(listener, &master);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == listener) {
// handle new connections
addrlen = sizeof remoteaddr;
newfd = accept(listener,
(struct sockaddr *)&remoteaddr,
&addrlen);
if (newfd == -1) {
perror("accept");
} else {
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) { // keep track of the max
fdmax = newfd;
}
printf("selectserver: new connection from %s on "
"socket %d\n",
inet_ntop(remoteaddr.ss_family,
get_in_addr((struct sockaddr*)&remoteaddr),
remoteIP, INET6_ADDRSTRLEN),
newfd);
}
} else {
// handle data from a client
memset(buf, 0, 256);
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("selectserver: socket %d hung up\n", i);
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
// we got some data from a client
for(j = 0; j <= fdmax; j++) {
// send to everyone!
if (FD_ISSET(j, &master)) {
// except the listener and ourselves
if (j != listener && j != i) {
if (send(j, buf, nbytes, 0) == -1) {
perror("send");
}
}
}
}
}
} // END handle data from client
} // END got new incoming connection
} // END looping through file descriptors
} // END for(;;)--and you thought it would never end!
return 0;
}
The reason a client can't receive a message until they send one is because.
fgets(message, 256,stdin);
Will keep "reading" (and will therefore block) until an EOF or a newline character has been read from the input stream
Also, note that
if( recv(sock , server_reply , 256 , 0) < 0)
blocks if there is nothing to read, which will prevent that user from sending more messages to the server until there is something new to read from the server. Assuming that you've played online games before, I hope that you can see that such a setup would be rather annoying!
So, we have to find someway of checking to see if we can read from STDIN and the server socket without incurring a block. Using select() will prevent us blocking on the sever socket, but it wouldn't work for STDIN whilst using fgets() to read input from the user. This is because, as mentioned above, fgets() blocks until an EOF or newline is detected.
The main solution I have in mind is to replace fgets with a method buffer_message() that will only read from STDIN when it won't block on read (we'll use select() to implement this). We'll then place what is read into a buffer. If there is a full message, this message will then be written to the server. Otherwise, we'll let the control keep going through the program until there is something to read or write.
This is code from a recent university assignment I did and so a small portion of the code isn't mine
Declarations:
//directives are above (e.g. #include ...)
//message buffer related delcartions/macros
int buffer_message(char * message);
int find_network_newline(char * message, int inbuf);
#define COMPLETE 0
#define BUF_SIZE 256
static int inbuf; // how many bytes are currently in the buffer?
static int room; // how much room left in buffer?
static char *after; // pointer to position after the received characters
//main starts below
Main:
//insert the code below into main, after you've connected to the server
puts("Connected\n");
//set up variables for select()
fd_set all_set, r_set;
int maxfd = sock + 1;
FD_ZERO(&all_set);
FD_SET(STDIN_FILENO, &all_set); FD_SET(sock, &all_set);
r_set = all_set;
struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0;
//set the initial position of after
after = message;
puts("Enter message: ");
//keep communicating with server
for(;;){
r_set = all_set;
//check to see if we can read from STDIN or sock
select(maxfd, &r_set, NULL, NULL, &tv);
if(FD_ISSET(STDIN_FILENO, &r_set)){
if(buffer_message(message) == COMPLETE){
//Send some data
if(send(sock, message, strlen(message) + 1, 0) < 0)//NOTE: we have to do strlen(message) + 1 because we MUST include '\0'
{
puts("Send failed");
return 1;
}
puts("Enter message:");
}
}
if(FD_ISSET(sock, &r_set)){
//Receive a reply from the server
if( recv(sock , server_reply , 256 , 0) < 0)
{
puts("recv failed");
break;
}
printf("\nServer Reply: %s\n", server_reply);
server_reply[0]='\0';
}
}
close(sock);
return 0;
//end of main
Buffer functions:
int buffer_message(char * message){
int bytes_read = read(STDIN_FILENO, after, 256 - inbuf);
short flag = -1; // indicates if returned_data has been set
inbuf += bytes_read;
int where; // location of network newline
// Step 1: call findeol, store result in where
where = find_network_newline(message, inbuf);
if (where >= 0) { // OK. we have a full line
// Step 2: place a null terminator at the end of the string
char * null_c = {'\0'};
memcpy(message + where, &null_c, 1);
// Step 3: update inbuf and remove the full line from the clients's buffer
memmove(message, message + where + 1, inbuf - (where + 1));
inbuf -= (where+1);
flag = 0;
}
// Step 4: update room and after, in preparation for the next read
room = sizeof(message) - inbuf;
after = message + inbuf;
return flag;
}
int find_network_newline(char * message, int bytes_inbuf){
int i;
for(i = 0; i<inbuf; i++){
if( *(message + i) == '\n')
return i;
}
return -1;
}
P.S.
if( send(sock , message , strlen(message) , 0) < 0)
The above can also block if there's no space to write to the server, but there's no need to worry about that here. Also, I'd like to point out a few things you should implement for your client and your server:
Whenever you send data over a network, the standard newline is \r\n, or carriage return / newline, or simply the network newline. All messages sent between the client and the server should have this appended at the end.
You should be buffering all data sent between the server and the client. Why? Because you're not guaranteed to receive all packets in a message in a single read of a socket. I don't have time to find a source, but when using TCP/IP, packets for a message/file don't have to arrive together, meaning that if you do read, you may not be reading all of the data you intend to read. I'm not well versed in this, so please investigate this more. Open to having this edited / corrected

Socket programming: recv/read issue

EDIT: the code below has been fixed to receive and send properly AND to account for the actual bytes of messages sent annd recieved (latter thanks to EJP)
I'm programming with C in Unix.
I have server and client that are supposed to exchange msgs. While client seems to send messages fine, server doesn't receive the messages the client is sending. I've tried using recv() and read() (i know they are practically the same thing but with extra flags on recv()) but I have no luck and I'm not really sure what the problem really is.
I put sleep(3) in the client code after every time it sends a message but i see that once client and server are connected, server immediately closes without waiting for the incoming messages. What am i doing wrong?
This is the client-side code:
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main(int argc, char * argv[])
{
int sockfd;
char * host;
char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
int msg_len;
struct hostent * hp;
struct sockaddr_in client_address, server_address;
printf("y halo thar\n");
// looking up from the host database
if (argc == 2)
host = argv[1];
else
exit(1);
printf("sdf\n");
hp = gethostbyname(host);
if (!hp)
exit(1);
printf("host found\n");
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
server_address.sin_port = htons(SERVER_TCP_PORT);
printf("set\n");
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("opened\n");
// connecting
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("connected\n");
int i;
for (i = 0; i < MAX_DATA_SIZE; ++i)
{
msg[i] = '.';
}
msg[MAX_DATA_SIZE-1] = '\0';
for(i = 0; i < 11; i++)
{
// send message to connected socket
msg_len = write(sockfd, msg, MAX_DATA_SIZE);
if(msg_len < 1)
printf("notsent\n");
else
printf("%i bytes sent\n", msg_len);
// recieve messages from connected socket
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
printf("not recieved\n");
else
{
printf("%i bytes received\n", msg_len);
printf(msg);
printf("\n");
}
}
// close connection
close(sockfd);
printf("closed\n");
}
and this is the server side
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main()
{
printf("o halo thar\n");
int sockfd, new_sockfd;
int client_addr_len;
char msg [MAX_DATA_SIZE];
int msg_len;
char got_msg [11] = "got ur msg\0";
struct sockaddr_in server_address, client_address;
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(SERVER_TCP_PORT);
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("socket is opened\n");
// binding
if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("socket is bound\n");
// listening
listen(sockfd,5);
printf("listening\n");
// block and wait for an incoming connection
client_addr_len = sizeof(client_address);
new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
if (new_sockfd < 0)
exit(1);
printf("accepted\n");
int i;
for( i = 0; i < 11; i++)
{
// recieve messages from connected socket
printf("waiting\n");
msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
{
printf("no msg recieved\n");
}
else
{
printf("bytes recieved: %i\n", msg_len);
}
// send message to connected socket
msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
if (msg_len < 1)
printf("not sent\n");
else
printf("%i bytes sent\n", msg_len);
}
// close connection
close(sockfd);
printf("socket closed. BYE! \n");
}
In the server code, the problem is on this line:
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
You are calling read on sockfd, but you need to call read or recv on new_sockfd (the socket returned by accept()). new_sockfd is the one that's connected to the client (sockfd is used to accept further connections - eg if another client connects).
You should read from the socket returned by accept.
Try to call read on the socket returned from accept.
Receiver Side:
while(1)
{
len=read(sd,buff,sizeof(buff));
if(len==0)
{
//End of File receving.
break;
}
else
{
st=fwrite(buff,sizeof(char),len,fp);
}
}
Send Side:
while(!feof(fp))
{
len=fread(buff,sizeof(char),MW,fp);
if(len==0)
{
//EOF
st=write(cd,&d,sizeof(int));
break;
}
else
{
st=write(cd,buff,len);
}
}
is the implementation based on stream or datagram?
there are some problem with your operation flow. the server might start to read before client send anything.
since client and server are separated, you can imagine them running concurrently.
right after your server side "accept" connection request, there might be possibly some handshake overhead occurs or network delays causing server app to execute ahead in time, attempt to extract data but meet with errors (no data received yet).
you can try this out by adding sleep in server code after accept connection, where client should have enough time to send the data.
another better solution is to make data retrieval cope with empty buffer or asynchronous read.

Resources