Simple C udp client/server fails - c

I am trying to write a server program that just displays any raw data it receives from anyone through udp. A client can send some data to it at any time. No errors appear except for "Socket error: Resource temporarily unavailable" which in other words mean that recvfrom has no data to receive (because it's presumably not getting any packets).
The client just sends "test!" to 127.0.0.0:12345, while the server listens with a non-blocking socket on port 12345. It may be worth noting that I am on linux.
Why is server not displaying the packets that it's obviously being sent from client? I don't see what I'm missing.
common.h
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;
int createSocket(uint16_t port)
{
int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (handle <= 0)
{
printf("failed to create socket\n");
return 0;
}
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(handle, (const sockaddr*)&address, sizeof(sockaddr_in)) < 0)
{
printf("failed to bind socket\n");
return 0;
}
int nonBlocking = 1;
if (fcntl(handle, F_SETFL, O_NONBLOCK, nonBlocking) == -1)
{
printf("failed to set non-blocking\n");
return 0;
}
return handle;
}
int sendData(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint16_t port, int handle, char* packet_data, int packet_size)
{
uint32_t address = (a << 24) | (b << 16) | (c << 8) | d;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(address);
addr.sin_port = htons(port);
int sent_bytes = sendto(handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&address, sizeof(sockaddr_in));
if (sent_bytes != packet_size)
{
printf("failed to send packet (%d/%d)\n", sent_bytes, packet_size);
return 0;
}
}
server.c
#include "common.h"
#include <time.h>
void main(void){
int socket = createSocket(12345);
if (!socket){
perror("Socket error");
}
int true=1;
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&true, 1);
// so that we can immediately reuse the port if the server stops running
char buffer[100] = "No data";
if(!listen(socket, 0)){
perror("Socket error");
}
//struct timespec delay = {0,33333333}; // 30Hz
struct timespec delay = {0,100000000}; // 100Hz
int running = 1;
int ret = 0;
while(running){
ret = recvfrom(socket, &buffer, 100, 0, NULL, NULL);
if (ret < 0){
perror("Socket error");
} else if (ret > 0){
printf("%d: %s\n", ret, buffer);
}
nanosleep(&delay,NULL);
}
}
client.c
#include "common.h"
void main(void){
int socket = createSocket(0);
printf("Started client on port %d\n", socket);
if(!sendData(127,0,0,0,12345, socket, "test!", 5)){
perror("Socket error");
} else {
printf("Sent data.\n");
}
}

I passed a pointer to address where I was supposed to pass a pointer to addr in common.h -> sendTo().
On top of that, I was sending packets to 127.0.0.0 when that should have been 127.0.0.1 (thanks #yano).
Corrected code:
int sendData(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint16_t port, int handle, char* packet_data, int packet_size)
{
uint32_t address = (a << 24) | (b << 16) | (c << 8) | d;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(address);
addr.sin_port = htons(port);
int sent_bytes = sendto(handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&addr, sizeof(sockaddr_in));
if (sent_bytes != packet_size)
{
printf("failed to send packet (%d/%d)\n", sent_bytes, packet_size);
return 0;
}
}

Related

Custom IP header for ICMP packet not working

I'm trying to make an ICMP packet with a custom IP header.
When I disable IP_HDRINCL to use the default IP header and cut out all the IP header related code, it works (I checked the checksums of the code below and the code that works with default headers, the ICMP packet is definitely valid in the code below).
The issue arrives when trying to use my own IP header, I don't receive any ICMP packets, indicating the packet didn't properly transmit or something went wrong.
I'm on Ubuntu 16.04 and compiling with GCC with the flags -std=c11 -Wall -Wextra -pedantic
#include <errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <arpa/inet.h>
#define PACKETSIZE 256
// Packet struct
struct packet {
struct iphdr ip; // IP Header
struct icmphdr hdr; // ICMP Header
char msg[PACKETSIZE - sizeof(struct icmphdr) - sizeof(struct iphdr)]; // Message
};
// Checksum function
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0;
unsigned short result;
for (sum = 0; len > 1; len -= 2) {
sum += *buf++;
}
if (len == 1) sum += *(unsigned char*)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int main(int argc, char* argv[])
{
// Enough arguments
if (argc < 2) {
printf("usage: ./tracert <server>\n");
return EXIT_FAILURE;
}
// Variables
struct hostent *hname;
struct sockaddr_in addr;
unsigned int i;
int sockfd, seq = 1;
struct packet pckt;
socklen_t len;
char buf[1024];
// Get host from domain
hname = gethostbyname(argv[1]);
memset(&addr, 0, sizeof(addr));
addr.sin_family = hname->h_addrtype;
addr.sin_port = htons(6969);
addr.sin_addr.s_addr = *(long *)hname->h_addr_list[0];
// Create ICMP RAW socket
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
printf("error on socket creation\n");
return EXIT_FAILURE;;
}
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &seq, sizeof(seq)) < 0) {
printf("error on default ip header settings\n");
return EXIT_FAILURE;
}
// Loop and receive/send packets
while (1) {
// Make packet
memset(&pckt, 0, sizeof(pckt));
// IP Header
pckt.ip.version = 4;
pckt.ip.ihl = 5;
pckt.ip.tot_len = htons(sizeof(pckt));
pckt.ip.ttl = 255;
pckt.ip.protocol = IPPROTO_ICMP;
pckt.ip.saddr = inet_addr("192.168.1.1");
pckt.ip.daddr = addr.sin_addr.s_addr;
pckt.ip.check = checksum(&pckt, sizeof(struct iphdr));
// ICMP Header
pckt.hdr.type = ICMP_ECHO;
pckt.hdr.un.echo.id = 0;
for (i = 0; i < sizeof(pckt.msg) - 1; i++) {
pckt.msg[i] = i+'0';
}
pckt.msg[i] = 0;
pckt.hdr.un.echo.sequence = seq;
pckt.hdr.checksum = checksum(&pckt.hdr, sizeof(struct icmphdr) + sizeof(pckt.msg));
// Send packet
if (sendto(sockfd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&addr, sizeof(addr)) <= 0) {
printf("error on sending packet\n");
return EXIT_FAILURE;
}
// Receive packet
len = sizeof(addr);
memset(buf, 0, sizeof(buf));
if (recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len) > 0) {
printf("packet received\n");
// Do more stuff here later...
}
// The while is there for later, for now I just want to send one packet
return EXIT_SUCCESS;
}
close(sockfd);
return EXIT_SUCCESS;
}

Send 100,000 UDP Packets to Client (C Socket Programming)

I'm working on a cool project and I need to send 100,000 UDP Packets from a Server to a Client with a Packet-to-Packet Delay of 10ms. The Server is Debian Server with a public IP Address. The Client is an other Debian PC with LTE USB-Modem. The Client has no public IP Address and knows the public IP Address of my Server. My 4G/LTE Provider doesn't provide public IP Adresses to thier clients.
I need to build a stable UDP Socket Connection but I'm struggling keeping the socket connection alive.
Can somebody help me?
thx
best regards
/**** CLIENT ****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 20009
int main()
{
int sock;
int size;
int nbytes, flags;
int i;
int a = 0;
char * cp;
char buffer[] = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
struct sockaddr_in target_pc, me;
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
target_pc.sin_family = PF_INET;
target_pc.sin_port = htons(PORT);
me.sin_family = PF_INET;
me.sin_port = htons(0);
me.sin_addr.s_addr = htonl(INADDR_ANY);
i = bind(sock, (struct sockaddr *) &me, sizeof(me));
if( i < 0)
{
printf("bind result: %d\n", i);
return -1;
}
nbytes = 200;
char str_addr[] = "155.55.25.25";
target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]);
while(1)
{
nbytes = strlen(buffer);
flags = 0;
sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc));
int addrlen = sizeof(target_pc);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen);
if((size > 0) && (size < 200))
{
buffer[size] = '\0';
i = puts((char *) buffer);
}
printf("%i --- Size: %lu\n", a, sizeof(buffer));
a = a + 1;
}
return 0;
}
Below my Server Code:
/*** SERVER ***/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 20009
void SleepMs(int ms)
{
usleep(ms*1000); //convert to microseconds
return;
}
int main()
{
int sock;
int size;
int nbytes, flags;
socklen_t addrlen;
int i;
char buffer[100];
char buffer2[] = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\0";
struct sockaddr_in server;
struct sockaddr_in from;
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
i = bind(sock, (struct sockaddr *) &server, sizeof(server));
if( i < 0){
printf("bind result: %d\n", i);
return -1;
}
else{
printf("Simple UDP server is ready!\n");
}
nbytes = 200;
flags = 0;
while(1)
{
addrlen = sizeof(from);
size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen);
if((size > 0) && (size < 200))
{
buffer[size] = '\0';
i = puts((char *) buffer);
}
printf("\n");
sock = socket(PF_INET,SOCK_DGRAM,0);
if(sock < 0)
{
printf("socket error = %d\n", sock);
return -1;
}
sendto(sock, buffer2, nbytes, flags, (struct sockaddr *)&from,addrlen);
SleepMs(10); // Packet-to-Packet Delay Time
}
return 0;
}
You can have the connection using IP of the server in this case 192.168.1.2
server.sin_addr.s_addr = inet_addr("192.168.1.2");
using this in both codes

udp socket - bind and connect succeed but send does not work [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to communicate through a connected-udp-socket between two peer's. The address information between the peers is transmitted via a server using tcp.
First each peer set's up an udp-socket, binds an address and then transmit the address information via tcp to a server. The server sends the connection information to the other peer.
When the peer receives the information it tries to 'connect' the udp-socket to the other peer. The connect call succeed, but send gives me the following error: 'errno: 89, Destination address required'.
peer.c:
#include "Socket.h"
#include "function.h"
int main (int argc, char** argv) {
if(argc != 4) {
printf("3 Parameter must be given.\nclient-ip server-ip server-port\n");
exit(-1);
}
struct sockaddr_in my_addr, server_addr, other_peer_addr;
address_info* msg_address_info;
header *msg;
int recv_done = 0;
int optval = 1;
int fd_udp, fd_server;
ssize_t len;
socklen_t my_addr_len;
fd_set rfds;
FD_ZERO(&rfds);
fd_udp = Socket(AF_INET, SOCK_DGRAM, 0);
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
my_addr.sin_len = sizeof(struct sockaddr_in);
#endif
my_addr.sin_port = 0; // any port
if ((my_addr.sin_addr.s_addr = (in_addr_t)inet_addr(argv[1])) == INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Bind(fd_udp, (const struct sockaddr *) &my_addr, sizeof(my_addr));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int));
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr_len = sizeof(my_addr);
//get the current address for server registration
Getsockname(fd_udp, (struct sockaddr *) &my_addr, &my_addr_len);
/* TCP Communication */
/* i use 127.0.0.1:55555 for the server */
fd_server = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
server_addr.sin_len = sizeof(struct sockaddr_in);
#endif
server_addr.sin_port = htons(atoi(argv[3]));
if ((server_addr.sin_addr.s_addr = (in_addr_t) inet_addr(argv[2]))
== INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Connect(fd_server, (const struct sockaddr *) &server_addr, sizeof(server_addr));
len = sizeof(address_info);
msg_address_info = malloc(len + get_padding(len));
memset((void*)msg_address_info, 0, len + get_padding(len));
msg_address_info->head.type = htons(30);
msg_address_info->head.length = htons(sizeof(address_info));
msg_address_info->ip = my_addr.sin_addr.s_addr;
msg_address_info->port = my_addr.sin_port;
Send(fd_server, msg_address_info, len + get_padding(len), 0);
free(msg_address_info);
while(!recv_done) {
FD_ZERO(&rfds);
FD_SET(fd_server, &rfds);
//data is ready for recv
if(FD_ISSET(fd_server, &rfds)) {
msg = recv_stream(fd_server);
if(msg != NULL) {
if(ntohs(msg->type) == 3) {
Close(fd_server);
recv_done = 1;
msg_address_info = (address_info *) msg;
other_peer_addr.sin_addr.s_addr = msg_address_info->ip;
other_peer_addr.sin_port = msg_address_info->port;
}
}
}
}
char buf[512];
memset((void*)&buf, 0, 512);
char* other_peer_ip;
int other_peer_port;
other_peer_ip = inet_ntoa(other_peer_addr.sin_addr);
other_peer_port = ntohs(other_peer_addr.sin_port);
printf("other_peer ip: %s\nother_peer port: %i\n", other_peer_ip, other_peer_port); //matches on bothe peer's
int ret_con = connect(fd_udp, (const struct sockaddr *) &other_peer_addr, sizeof(other_peer_addr));
fprintf(stderr, "ret_con: %i, errno: %i, %s\n", ret_con, errno, strerror(errno));
int ret_send = send(fd_udp, buf, 512, 0);
if(ret_send < 0) {
fprintf(stderr, "ret_send: %i, errno: %i, %s\n", ret_send, errno, strerror(errno));
}
}
function.h:
#define BUFFER_SIZE (1<<16)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <err.h>
#include <netdb.h>
#include <errno.h>
#include "Socket.h"
typedef struct {
uint16_t type;
uint16_t length;
} header;
typedef struct {
header head;
uint32_t ip;
uint16_t port;
} address_info;
int get_padding(int length);
void* recv_stream(int fd);
functions.c:
#include "functions.h"
void* recv_stream(int fd) {
if(fd < 0) {
fprintf(stderr, "recv_stream: Invaild fd\n");
return NULL;
}
ssize_t len;
int msg_length;
char buf[BUFFER_SIZE];
char* msg;
len = recv(fd, &buf, BUFFER_SIZE, MSG_PEEK);
//Client has closed the connection
if(len <= 0) {
fprintf(stderr, "recv_stream: Client closed the connection.\n");
exit(-1);
}
#ifdef DEBUG
printf("PEEKED %zd bytes.\n", len);
#endif
if(len < sizeof(header)) {
fprintf(stderr, "recv_stream: Message to small no header\n");
return NULL;
}
header *head = (header *) buf;
msg_length = ntohs(head->length);
if(len < msg_length) {
fprintf(stderr, "recv_stream: Message to small\n");
return NULL;
}
else if(len >= msg_length + get_padding(msg_length)) {
msg = malloc(msg_length + get_padding(msg_length));
len = Recv(fd, msg, msg_length + get_padding(msg_length), 0);
head = (header *) msg;
}
return head;
}
int get_padding(int length) {
if(length <= 0) {
fprintf(stderr, "get_padding: wrong length");
}
int pad = length % 4;
if(pad == 3)
pad = 1;
else if(pad == 1)
pad = 3;
return pad;
}
Socket.c with Wrapper functions
int Socket(int fd, int type, int protocol) {
int n;
if((n=socket(fd,type,protocol)) < 0) {
perror("socket");
exit(-1);
}
return n;
}
/* many more */
I read already following question Can you bind() and connect() both ends of a UDP connection but it did not solve my problem.
The transfer of the address information seems to be correct. I printed the send and received addresses on both peers and they match.
I'm stucked on this problem and can't figure out my mistake. Can you help me?
Edit:
provided new example
Now i get the following error:
ret_con: -1, errno: 97, Address family not supported by protocol
ret_send: -1, errno: 89, Destination address required
You are not populating the sin_family field of other_peer_addr before calling connect() on the UDP socket. You are only populating the sin_addr and sin_port fields, which is not enough. connect() needs to be told the type of address being passed to it and that must use the same family as the socket (just like with bind()). Since you are not populating the sin_family field, it contains a random value from the stack, and that is causing connect() to fail with the "Address family not supported" error, and send() cannot be called on an unconnected socket, thus causing the "Destination address required" error.

C, Socket, pthread: read doesn't work on a new thread

I'm making a client-server program in C using threads.
I've got this problem: on the server, on thread #1 (number_one), function "read" works fine. But when I create another thread #2 (number_two), on this one something goes wrong. Parameters are passed in the right way (I think).
-->thread number_one
...
char message[256];
int new_connection=accept(master_sock,NULL,NULL);
pthread_t temp
if(pthread_create(&temp , NULL , number_two , (void*) &new_connection))
{
perror("pthread_create failed");
exit(-2);
}
else
{
puts("number_two created");
if(read(new_connection, message, 256) > 0)
printf("Message from client is %s", message);
}
if(pthread_detach(temp))
{
perror("detach failed");
exit(-3);
}
...
---> thread number_two
void *number_two(void *sock_desc)
{
int sock = *(int*)sock_desc;
int read_size;
char client_message[2000];
read_size=read(sock, client_message, 256);
client_message[read_size]='\0';
return 0;
}
In "number_one", read waits an input from the client, and then it sets correctly the buffer "message".
In "number_two", read does not wait the client and does not set the buffer "client_message".
Thank you.
Please try my code? it works, I think it is the same with your code.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define INVALID_SOCKET_FD (-1)
int create_tcp_server_socket(unsigned short port, bool bind_local, int backlog,
char *caller_name)
{
int socket_fd = INVALID_SOCKET_FD;
struct sockaddr_storage server_addr;
unsigned int yes = 1;
// just try ipv4
if (socket_fd < 0 && (socket_fd = socket(PF_INET, SOCK_STREAM, 0)) >= 0) {
struct sockaddr_in *s4 = (struct sockaddr_in *)&server_addr;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
memset(&server_addr, 0, sizeof(server_addr));
s4->sin_family = AF_INET;
s4->sin_port = htons(port);
if (bind_local)
s4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else
s4->sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(socket_fd, (struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
close(socket_fd);
printf("Server: Failed to bind ipv4 server socket.\n");
return INVALID_SOCKET_FD;
}
}
else if (socket_fd < 0) {
printf("Server: Failed to create server socket.\n");
return INVALID_SOCKET_FD;
}
if (listen(socket_fd, backlog) < 0) {
close(socket_fd);
printf("Server: Failed to set listen.\n");
return INVALID_SOCKET_FD;
}
return socket_fd;
}
pthread_t temp;
void *number_two(void *sock)
{
char buf[1024];
int fd = *(int *)sock;
int nread = read(fd, buf, 1024);
write(STDOUT_FILENO, buf, nread);
return NULL;
}
int main()
{
pid_t pid;
if ((pid = fork()) < 0) {
}
else if (pid > 0) { // parent, server
char buf[1024];
int fd = create_tcp_server_socket(8787, false, 10, "zz");
int new_fd = accept(fd, NULL, 0);
pthread_create(&temp, NULL, number_two, (void *)&new_fd);
}
else { // child, client
uint32_t ip;
struct hostent *hp = gethostbyname("localhost");
memcpy(&ip, hp->h_addr_list[0], hp->h_length);
struct sockaddr_in server_addr;
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = ip;
server_addr.sin_port = htons(8787);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
write(fd, "abcd", 4);
}
pause();
return 0;
}

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.

Resources