file transfer using stop and wait protocol and udp protocol in C - c

I want to send a file using UDP with stop and wait protocol. I have a client and server code that is working fine with a single input string.
I was trying to change the code for file transfer but no success. Can anyone help me with minimal changes to convert the below code for using file transfer?
code of client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
typedef struct packet{
char data[1024];
}Packet;
typedef struct frame{
int frame_kind; //ACK:0, SEQ:1 FIN:2
int sq_no;
int ack;
Packet packet;
}Frame;
int main(int argc, char **argv[]){
if (argc != 2){
printf("Usage: %s <port>", argv[0]);
exit(0);
}
int port = atoi(argv[1]);
int sockfd;
struct sockaddr_in serverAddr;
char buffer[1024];
socklen_t addr_size;
int frame_id = 0;
Frame frame_send;
Frame frame_recv;
int ack_recv = 1;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
while(1){
if(ack_recv == 1){
frame_send.sq_no = frame_id;
frame_send.frame_kind = 1;
frame_send.ack = 0;
printf("Enter Data: ");
scanf("%s", buffer);
strcpy(frame_send.packet.data, buffer);
sendto(sockfd, &frame_send, sizeof(Frame), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
printf("[+]Frame Send\n");
}
int addr_size = sizeof(serverAddr);
int f_recv_size = recvfrom(sockfd, &frame_recv, sizeof(frame_recv), 0 ,(struct sockaddr*)&serverAddr, &addr_size);
if( f_recv_size > 0 && frame_recv.sq_no == 0 && frame_recv.ack == frame_id+1){
printf("[+]Ack Received\n");
ack_recv = 1;
}else{
printf("[-]Ack Not Received\n");
ack_recv = 0;
}
frame_id++;
}
close(sockfd);
return 0;
}
Code of server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
typedef struct packet{
char data[1024];
}Packet;
typedef struct frame{
int frame_kind; //ACK:0, SEQ:1 FIN:2
int sq_no;
int ack;
Packet packet;
}Frame;
int main(int argc, char** argv){
if (argc != 2){
printf("Usage: %s <port>", argv[0]);
exit(0);
}
int port = atoi(argv[1]);
int sockfd;
struct sockaddr_in serverAddr, newAddr;
char buffer[1024];
socklen_t addr_size;
int frame_id=0;
Frame frame_recv;
Frame frame_send;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
addr_size = sizeof(newAddr);
while(1){
int f_recv_size = recvfrom(sockfd, &frame_recv, sizeof(Frame), 0, (struct sockaddr*)&newAddr, &addr_size);
if (f_recv_size > 0 && frame_recv.frame_kind == 1 && frame_recv.sq_no == frame_id){
printf("[+]Frame Received: %s\n", frame_recv.packet.data);
frame_send.sq_no = 0;
frame_send.frame_kind = 0;
frame_send.ack = frame_recv.sq_no + 1;
sendto(sockfd, &frame_send, sizeof(frame_send), 0, (struct sockaddr*)&newAddr, addr_size);
printf("[+]Ack Send\n");
}else{
printf("[+]Frame Not Received\n");
}
frame_id++;
}
close(sockfd);
return 0;
}
Please help me. I am a beginner and taking references but not able to achieve.

Related

Error in recvfrom in C socket programming?

Sorry for my not perfet english
I have to implement reliable communication using UDP protocol; for start, i'm tring realize a simple program; a client send a message to server with NULL in buffer; the servers understands it as a request, then sends to client response, which is a number;
code client:
/*
* newClient.c
*
* Created on: 22 lug 2017
* Author: claudio
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SERV_PORT 5193
#define MAXLINE 1024
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
int request_to_server(int sockfd,int* x,struct sockaddr_in addr)
{
int n;
if(sendto(sockfd, NULL, 0, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
err_exit("sendto\n");
n = recvfrom(sockfd,(char*)x,sizeof(int),0,NULL,NULL);
if (n < 0) {
perror("errore in recvfrom");
exit(1);
}
if(n > 0) {
printf("client received: %d\n",*(int*)x);
}
return 1;
}
int main(int argc, char *argv[ ]) {
int sockfd;
struct sockaddr_in servaddr;
int x;
if (argc != 2) {
fprintf(stderr, "utilizzo: daytime_clientUDP <indirizzo IP server>\n");
exit(1);
}
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { /* crea il socket */
perror("errore in socket");
exit(1);
}
memset((void *)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
err_exit("error in inet_pton for %s");
}
if(request_to_server(sockfd,&x,servaddr))
printf("client received %d from server\n",x);
exit(EXIT_SUCCESS);
}
this is server code:
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define SERV_PORT 5193
#define MAXLINE 1024
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
int generate_casual()
{
int x = random()%1000 + 1; //number between 1 and 1000
return x;
}
void listen_request(int sockfd,char* buff,struct sockaddr_in* addr,socklen_t* len)
{
struct sockaddr_in servaddr = *addr;
socklen_t l = *len;
printf("listening request\n");
if ( (recvfrom(sockfd, buff, MAXLINE, 0, (struct sockaddr *)&servaddr, &l)) < 0){
printf("errno code: %d\n",errno);
err_exit("recvfrom\n");
}
*addr = servaddr;
*len = l;
return;
}
int main(int argc, char **argv)
{
(void) argc;
(void) argv;
int sockfd;
socklen_t len;
struct sockaddr_in addr;
char buff[MAXLINE];
srand(time(NULL));
memset((void *)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERV_PORT); /* numero di porta del server */
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
err_exit("errore in socket");
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("errore in bind");
exit(1);
}
listen_request(sockfd,buff,&addr,&len);
int n_ack = generate_casual();
//char* p =(char*)&n_ack;
if (sendto(sockfd, (char*)&n_ack, sizeof(int), 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
err_exit("sendto");
}
printf("server: client is connected\n");
return 0;
}
when i run, sometimes client receives correctly number; but sometimes i have an error on recvfrom with msg "Invalid argument" ed errno code is 22;
why this?I have no idea in which case it runs and when it doesn't work, code is the same..

Sending UDP packet to 2 clients and only one receive

(sorry by advance for my English...)
I am working on a network between a PC and a set of Zedboards connected by Ethernet. I use the UDP protocol, and here's my problem:
- All my cards and my PC are correctly connected to a switch and have their own IPs (192.168.1.15 for PC , and 11/12 for cards).
- When I try to send a simple packet with unix sockets with the code below, only the last message is received (but both seem to be send) (plus, no error or warning on compilation)
- If I switch the two sending, it is always the last which arrive at destination so it is not a card problem...
main.c
#include "send_tool.h"
static int PORT;
static char LOCAL_ADDRESS[50];
static SOCKADDR_IN client_list[NB_CLIENTS];
static int uc_sock;
int main(int argc, char **argv)
{
char buffer[BUF_SIZE];
int actual;int i;
memset(buffer,0, sizeof(buffer));
SOCKADDR_IN csin = { 0 };
if(argc < 3)
{
PORT = 2005;
sprintf(LOCAL_ADDRESS, "192.168.1.15");
printf("Valeurs de parametre forcees: %d\t%s\n", PORT, LOCAL_ADDRESS);
}
else
{
PORT = atoi(argv[1]);
sprintf(LOCAL_ADDRESS, argv[2]);
}
uc_sock = init_UC_connection(LOCAL_ADDRESS, PORT);
while(actual < NB_CLIENTS)
{
read_UDP(uc_sock, &csin, buffer);
if(!strncmp(buffer, "free:",5))
{
//add_client(client_list, csin);
client_list[actual].sin_addr.s_addr = csin.sin_addr.s_addr;
client_list[actual].sin_port = csin.sin_port;
client_list[actual].sin_family = csin.sin_family;
memcpy(client_list[actual].sin_zero, csin.sin_zero, 8);
//sprintf(buffer, "salut");
//write_UDP(uc_sock, &client_list[actual], buffer, strlen(buffer));
actual++;
}
}
printf("************************************\n");
printf("0: %s:%d/%d\n", inet_ntoa(client_list[0].sin_addr), ntohs(client_list[0].sin_port), client_list[0].sin_family);
printf("1: %s:%d/%d\n", inet_ntoa(client_list[1].sin_addr), ntohs(client_list[1].sin_port), client_list[1].sin_family);
printf("************************************\n");
sprintf(buffer, "au revoir");
write_UDP(uc_sock, &client_list[0], buffer, strlen(buffer));
write_UDP(uc_sock, &client_list[1], buffer, strlen(buffer));
memset(buffer, 0, sizeof(buffer));
while(read_UDP(uc_sock, &csin, buffer) > 0){}
close(uc_sock);
return 0;
}
send_tool.h
/* STD LIBS */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
//#include <sys/types.h>
//#include <sys/stat.h>
/* SOCKETS */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
/* TIME */
#include <sys/timerfd.h>
#include <sys/time.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#define BUF_SIZE 60000
#define MULTICAST_ADDRESS "224.0.0.1"
#define NB_CLIENTS 2
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
typedef struct in_addr IN_ADDR;
int init_UC_connection(char LOCAL_ADDRESS[], int port);
void write_UDP(int sock, SOCKADDR_IN *sin, const char *buffer, size_t buff_len);
int read_UDP(int sock, SOCKADDR_IN *sin, char *buffer);
send_tool.c
#include "send_tool.h"
int init_UC_connection(char LOCAL_ADDRESS[], int port)
{
/* UDP so SOCK_DGRAM */
int sock = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN sin = { 0 };
struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
if(sock == -1)
{
perror("socket()");
exit(errno);
}
sin.sin_addr.s_addr = inet_addr(LOCAL_ADDRESS);
sin.sin_port = htons(port);
sin.sin_family = AF_INET;
if(bind(sock,(SOCKADDR *)&sin, sizeof sin) == -1)
{
perror("bind()");
exit(errno);
}
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0) {
perror("Error");
}
return sock;
}
void write_UDP(int sock, SOCKADDR_IN *sin, const char *buffer, size_t buff_len)
{
socklen_t sinsize = 16;//sizeof *sin;
printf("sinsize : %d\n", sinsize);
int n;
size_t i;
if((n=sendto(sock, buffer, buff_len, 0, (SOCKADDR *) sin, sinsize)) < 0)
{
perror("send()");
exit(errno);
}
printf("envoi (sinsize = %d; n = %d)|%s| a %s:%d/%d termine \n", sinsize, n, buffer, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), sin->sin_family);
}
int read_UDP(int sock, SOCKADDR_IN *sin, char *buffer)
{
int n = 0;
socklen_t sinsize = sizeof *sin;
if((n = recvfrom(sock, buffer, BUF_SIZE - 1, 0, (SOCKADDR *) sin, &sinsize)) < 0)
{
perror("recvfrom()");
exit(errno);
}
printf("recu (sinsize = %d; n = %d)|%s| depuis %s:%d/%d termine \n", sinsize, n, buffer, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), sin->sin_family);
return n;
}
client.c
#include "receive_tool.h"
static int PORT;
static char LOCAL_ADDRESS[50];
/* main function, launching the Server application*/
int main(int argc, char **argv)
{
int uc_sock;
char free_msg[30];
memset(free_msg, 0, sizeof(free_msg));
char buffer[60000];
memset(buffer, 0, sizeof(buffer));
if(argc < 3)
{
PORT = 2005;
sprintf(LOCAL_ADDRESS, "192.168.1.12");
//printf("Valeurs de parametre forcees: %d\t%s\n", PORT, LOCAL_ADDRESS);
}
else
{
PORT = atoi(argv[1]);
sprintf(LOCAL_ADDRESS, argv[2]);
}
sprintf(free_msg, "free:%s", LOCAL_ADDRESS);
SOCKADDR_IN server_sin = { 0 }, receive_sin = { 0 };
server_sin.sin_addr.s_addr = inet_addr(SERVER_ADDRESS); // addresse multicast vers les serveurs
server_sin.sin_family = AF_INET;
server_sin.sin_port = htons(PORT);
memset(&server_sin.sin_zero, 0, sizeof(server_sin.sin_zero));
uc_sock = init_UC_connection(LOCAL_ADDRESS, PORT);
write_UDP(uc_sock, &server_sin, free_msg);
time_t chrono_begin;
chrono_begin = time(NULL);
chrono_begin+= 5;
while(time(NULL) <= chrono_begin)
{
if(read_UDP(uc_sock, &receive_sin, buffer)<0) continue;
write_UDP(uc_sock, &server_sin, buffer);
}
close(uc_sock);
return 0;
}
Do you have any idea why this happen?
Thank you for your help.
The problem was caused by the Zedboards which used the same MAC address. Then, the switch sent only to the last IP address connected to the MAC address.
Bye

Different behavior about port number between CentOS and Windows

I’ve made C programs they are the server and the client. They send message each other by using udp.
The server waits until message is sent from the client.
When I type some message from the client console, the client will send the message to the server.
The serve receives the message from the client then the server will echo the message on its console and send back same message to the client.
Finaly the client shows message on its console that the server sent back the message.
In this procedure the client shows its source port number on its console.And the server also shows client's source port number that message was sent with recvfrom ()
Strangely, source port number is different between the client and the server if I run them on windows7 but if I run them on CentOS6.4 the source port number is same.
Does anyone know how this happens?
My code are following.
[server]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
int charToInt(char myText[]) {
char s[] = {'1', '2', '3', '4'};
const int n = strlen(myText);
int i, m = 0;
for(i = 0; i < n; ++ i){
m = m * 10 + myText[i] - '0';
}
printf("%d\n", m);
return m;
}
int
main(int argc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
int sock;
struct sockaddr_in addr;
struct sockaddr_in from;
int sockaddr_in_size = sizeof(struct sockaddr_in);
char buf[2048];
char comnd[2048];
char *bye="bye";
printf("############# udpServer start prot number is %d\n",charToInt(argv[1]));
sock = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(charToInt(argv[1]));
addr.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
while (!strncmp(buf,bye,3)==0){
memset(buf, 0, sizeof(buf));
recvfrom(sock, buf, sizeof(buf), 0,(struct sockaddr *)&from, &sockaddr_in_size);
printf("recived '%s'(%d) from %s:%d\n", buf, strlen(buf),
inet_ntoa(from.sin_addr),ntohs(from.sin_port));
sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, sizeof(from));
printf("send back %s to %s:%d\n", buf,inet_ntoa(from.sin_addr),ntohs(from.sin_port));
printf("\n");
}
printf("bye now");
close(sock);
return 0;
}
[client]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <errno.h>
int charToInt(char myText[]) {
char s[] = {'1', '2', '3', '4'};
const int n = strlen(myText);
int i, m = 0;
for(i = 0; i < n; ++ i){
m = m * 10 + myText[i] - '0';
}
printf("%d\n", m);
return m;
}
int getMyPortNum(int sock)
{
struct sockaddr_in s;
socklen_t sz = sizeof(s);
getsockname(sock, (struct sockaddr *)&s, &sz);
return s.sin_port;
}
int
main(int agrc,char *argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
char *host;
int port;
int sock;
struct sockaddr_in dst_addr = {0};
struct sockaddr_in src_addr = {0};
struct sockaddr_in rcv_addr = {0};
int sockaddr_in_size = sizeof(struct sockaddr_in);
int defPortNum;
char message[2048];
char comnd[2048];
int i;
int ret;
int connect_ret;
int bind_ret;
char *p;
char buf[2048];
host=argv[1];
port=charToInt(argv[2]);
printf("host = %s\n",host);
printf("port = %d\n",port);
sock = socket(AF_INET, SOCK_DGRAM, 0);
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(host);
dst_addr.sin_port = htons(port);
printf("getMyPortNum before bind() is %d\n",ntohs(src_addr.sin_port));
bind_ret = 0;
bind_ret = bind(sock,(struct sockaddr *)&src_addr,sizeof(src_addr));
src_addr.sin_port = getMyPortNum(sock);
printf("Default Client port is %d\n",ntohs(src_addr.sin_port));
if(bind_ret>=0){
printf("bind() error ret = %d:%s\n",bind_ret,strerror(errno));
perror("bind()");
return bind_ret;
}
memset(message, 0, sizeof(message));
memset(comnd, 0, sizeof(comnd));
memset(buf,0,sizeof(buf));
while(!strncmp(comnd,"bye",3)==0){
if(strncmp(message,"bye",3)==0){
strcpy(comnd,message);
}else{
printf("typ your message (exit:stop Client bye:stop server)>>>\t");
fgets(comnd,sizeof(comnd),stdin);
comnd[strlen(comnd) - 1] = '\0';
strcpy(message,comnd);
}
ret = sendto(sock, message, strlen(message), 0,
(struct sockaddr *)&dst_addr, sizeof(dst_addr));
printf("Server port (dst port) for sending is %d\n",ntohs(dst_addr.sin_port));
if(ret<0){
printf("Send Error ret = %d:%s\n",ret,strerror(errno));
return ret;
}else{
printf("Waiting for sendBack !!!\n");
printf("Client port for recieving is %s:%d\n"
,inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port));
ret = recvfrom(sock, buf, sizeof(buf),
0,(struct sockaddr *)&rcv_addr, &sockaddr_in_size);
if(ret<0){
printf("ReciveError ret = %d\n",ret);
}else{
printf("Sentback %s from %s:%d\n"
,buf,inet_ntoa(rcv_addr.sin_addr)
,ntohs(rcv_addr.sin_port));
}
}
}
close(sock);
}
It is possible that a new random source port gets used every time you call sendto(), unless you explicitly bind() the client socket to a specific source port (and not rely on the OS doing an implicit bind() for you). That is the only reliable way the client could display its own source port, since sendto() does not report the source port that is actually used. Remember, unlike TCP, UDP is connection-less, so the source port is not required to stay consistent unless you force it.
Update: your client code has one line where it is logging a network byte order port number when it should be logging a host byte order port number instead:
//printf("getMyPortNum before bind() is %d\n",myName.sin_port);
printf("getMyPortNum before bind() is %d\n",port);
Aside from that, why did you create your own charToInt() function, instead of using a standard function, like atoi() or strtol()?
You are also not doing very good error handling.
Try something more like this instead:
[Server]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int printerror2(char func[], int errnum)
{
printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
perror(func);
return errnum;
}
int printerror(char func[])
{
return printerror2(func, errno);
}
int main(int argc, char *argv[])
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ret != 0)
return printerror2("WSAStartup()", ret);
int sock;
in_port_t port;
struct sockaddr_in addr;
struct sockaddr_in from;
int from_size;
char buf[2048];
port = atoi(argv[1]);
printf("############# udpServer port number is %hu\n", port);
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1)
return printerror("socket()");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1)
return printerror("bind()");
do
{
from_size = sizeof(from);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, &from_size);
if (ret == -1)
return printerror("recvfrom()");
printf("received '%*s'(%d) from %s:%hu\n",
ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
ret = sendto(sock, buf, ret, 0, (struct sockaddr *)&from, from_size);
if (ret == -1)
return printerror("sendto()");
printf("sent back '%*s'(%d) to %s:%hu\n",
ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
printf("\n");
}
while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));
printf("bye now");
close(sock);
return 0;
}
[Client]
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <sys/types.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int printerror2(char func[], int errnum)
{
printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
perror(func);
return errnum;
}
int printerror(char func[])
{
return printerror2(func, errno);
}
int getMyPortNum(int sock, in_port_t *port)
{
struct sockaddr_in s;
socklen_t sz = sizeof(s);
int ret = getsockname(sock, (struct sockaddr *)&s, &sz);
if (ret == 0)
*port = s.sin_port;
return ret;
}
int main(int agrc, char *argv[])
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ret != 0)
return printerror2("WSAStartup", ret);
char *host;
in_port_t port;
int sock;
struct sockaddr_in dst_addr;
struct sockaddr_in src_addr;
struct sockaddr_in from_addr;
int from_size;
char buf[2048];
host = argv[1];
port = atoi(argv[2]);
printf("host = %s\n", host);
printf("port = %hu\n", port);
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1)
return printerror("socket()");
memset(&src_addr, 0, sizeof(src_addr));
src_addr.sin_family = AF_INET;
src_addr.sin_addr.s_addr = INADDR_ANY;
src_addr.sin_port = 0;
ret = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr));
if (ret == -1)
return printerror("bind()");
ret = getMyPortNum(sock, &(src_addr.sin_port));
if (ret == -1)
return printerror("getsockname()");
printf("Client port is %hu\n", ntohs(src_addr.sin_port));
memset(&dst_addr, 0, sizeof(dst_addr));
dst_addr.sin_family = AF_INET;
dst_addr.sin_addr.s_addr = inet_addr(host);
dst_addr.sin_port = htons(port);
do
{
printf("type your message (exit: stop Client, bye: stop server)>>>\t");
fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "exit") == 0)
break;
ret = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
if (ret == -1)
return printerror("sendto()");
printf("Waiting for send back !!!\n");
from_size = sizeof(from_addr);
ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from_size, &from_size);
if (ret == -1)
return printerror("recvfrom()");
printf("Received '%*s' from %s:%hu\n",
ret, buf, inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
}
while ((ret != 3) || (strncmp(buf, "bye", 3) != 0));
close(sock);
return 0;
}
return s.sin_port;
That should be
return ntohs(s.sin_port);
It works in CentOS presumably because 'ntohs(i) == i' there.

error in client server udp c

I want to establish connection between two pc using client and server using C
I have been able to sent data from client and receive by server.
but when server want to sent data the error are appear in server side:
segmentation fail :11
here my program:
in client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MYPORT 4950
#define MAXBUFLEN 100
int main() {
char no[16], dt[30];
printf("‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐\n");
printf("To : ");
scanf("%s", no);
while(1){
printf("Me : ");
scanf("%s", dt); send(no, dt); receive();
}
}
int send(char no[], char dt[])
{
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
if((he = gethostbyname(no)) == NULL)
{
perror("gethostbyname");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
{ //40
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr=*((struct in_addr*)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
if((numbytes=sendto(sockfd,dt,strlen(dt),0,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)))==-1)
{
perror("sendto");
exit(1);
}
close(sockfd);
return 0;
}
int receive()
{
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
char buf[MAXBUFLEN];
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1) //68
{
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero),'\0',8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
perror("bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
if((numbytes=recvfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,&addr_len))==-1)
{
perror("recvfrom");
exit(1); }
buf[numbytes]='\0';
printf("%s : \"%s\"\n", inet_ntoa(their_addr.sin_addr), buf);
close(sockfd);
return 0;
}
and server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MYPORT 4950
#define MAXBUFLEN 100
char noip[50];
int main()
{
char no[16];
char dt[30];
printf("‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐\n");
receive();
strcpy (no, noip);
while(1){
printf("Me : ");
scanf("%s", dt);
send( dt);
receive();
}
}
int send(char dt[30]) {
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr=*((struct in_addr*)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
if((numbytes=sendto(sockfd,dt,strlen(dt),0,(struct sockaddr *)&their_addr,sizeof(struct sockaddr)))==-1)
{
perror("sendto");
exit(1); }
close(sockfd);
return 0; }
int receive() {
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
char buf[MAXBUFLEN];
char no[16];
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket");
exit(1); }
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero),'\0',8);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1){
perror("bind");
exit(1); }
addr_len = sizeof(struct sockaddr);
if((numbytes=recvfrom(sockfd,buf,MAXBUFLEN-1,0,(struct sockaddr *)&their_addr,&addr_len))==-1)
{
perror("recvfrom");
exit(1);}
buf[numbytes]='\0';
printf("%s : \"%s\"\n", inet_ntoa(their_addr.sin_addr), buf);
strcpy(no,inet_ntoa(their_addr.sin_addr));//copy data ke varibel no
close(sockfd);
return 0;
}
Any sugestion?
Do a debug build (option -g) and then call the gdb. It opens a prompt where you use
file "a.out"
to load the executable and afterwards call "run" to actually run you program under debugger's control. When the segfault happens, call "backtrace" and it should tell you the function and maybe the line where it happens.
But when I see the code, my first guess would be the input char array. Do you enter more than 29 characters when sending? ;)

gcc: wrong behaviour after new variable was added

I am writing simple programs: server and client. You know, I am just learning all these stuff.
I added new variable (fileUp in server.c) and the client just crashed. I debugged it with gdb. The client can't read anything from the socket. Without that one variable works fine.
I did compile these programs with both gcc and g++ with -Wall. No errors, no warnings.
Programs are as simple as they can be. I don't understand what is wrong.
Any hint'll be appreciated.
server.c
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
struct sockaddr_in address, client;
int s = socket(AF_INET, SOCK_STREAM, 0);
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
#define PORT 54321
address.sin_port = htons(PORT);
if(bind(s, (struct sockaddr *)&address, sizeof(address))<0) {
perror("nie udał się bind");
exit(-1);
}
if(listen(s, 5)<0) {
perror("nie udał się listen");
exit(-1);
}
socklen_t client_len;
int c = accept(s, (struct sockaddr *)&client, &client_len);
int file = open("../data", O_RDONLY);
if(file<0) {
perror("nie udało się otworzyć pliku");
exit(-1);
}
#define MAX 1024
char buf[MAX];
int n = read(file, buf, MAX);
int fileUp = n;
do {
write(c, buf, MAX);
buf[n-1] = '\0';
printf("%d: %s\n", n, buf);
/*fileUp += n;
printf("pobrano: %d\n", fileUp);*/
n = read(file, buf, MAX);
getchar();
} while(n != 0);
close(c);
close(s);
return 0;
}
client.c
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
struct sockaddr_in address;
int s = socket(PF_INET, SOCK_STREAM, 0);
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
#define PORT 54321
address.sin_port = htons(PORT);
if(inet_pton(AF_INET, argv[1], &address.sin_addr) <=0) {
perror("podano nieprawidłowy adres");
exit(-1);
}
if(connect(s, (struct sockaddr *)&address, sizeof(address))<0) {
perror("nie można się połączyć");
exit(-1);
}
#define MAX 1024
char buf[MAX];
int n = read(s, buf, MAX);
int fileDown = n;
do {
buf[n-1] = '\0';
printf("%d: %s\n", n, buf);
n = read(s, buf, MAX);
fileDown += n;
printf("pobrano: %d\n", fileDown);
} while(n != 0);
close(s);
return 0;
}
socklen_t client_len; should be socklen_t client_len = sizeof(client);
The stack layout will change when you add your new variable - so the uninitialized value in client_len just happened to work before, it doesn't after - most likely making your accept call fail, and then you're trying to write to an invalid FD.
You should of course also check the return value of accept

Resources