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.
Related
I have a piece of C code that should connect to www.google.com and make a HTTP GET request, but when I run it, it stays on "Connecting.." for about 30 seconds before returning "Connection Failed" and an exit return value of 255. What am I doing wrong?
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 8000
struct hostent *hostinfo;
int main(void) {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hostname = "www.google.com";
char *request = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
printf("\n Connection Failed \n");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
valread = read(sock, buffer, 1024);
printf("%s\n", buffer);
return 0;
}
I see two major problems.
You use the wrong port. Use port 80 for http.
Your read and printf is a dangerous combination that could easily cause access out of bounds (and undefined behavior). What you read from the socket will not be null terminated. You could instead do something like this:
...
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
This will however block when everything has been read. See non-blocking I/O or consider using select, epoll or poll to wait for available data on sockets.
If you are only interested in getting the response and then disconnect, you could however use Connection: close to close the connection after the server has sent the response. Full code below:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 80
int main(void) {
int sock = 0, valread;
struct hostent *hostinfo;
struct sockaddr_in serv_addr;
const char *hostname = "www.google.com";
const char *request = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: close\r\n\r\n"; // <- added
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
perror("connect()");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
}
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
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;
}
I posted my code here: communication between windows client and linux server?
I am performing communication between client and server.I know that udp is a connectionless program nothing but it wont send any response back to the client. If i want to send a response back to the client then what should i do ??
I solved all my errors in the above link but I got a doubt w.r.t sending a response back to the client. so i am re posting here.
This is the code I wrote when I start learning socket programming, hope it helps:
server
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct sockaddr_in server;
struct sockaddr_in client;
int socket_fd;
int ret;
char buf[255];
int len = sizeof(struct sockaddr_in);
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_fd < 0)
{
printf("socket error\n");
return -1;
}
server.sin_family = AF_INET;
server.sin_port = htons(5900);
server.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr));
if(ret)
{
printf("error while binding\n");
return -1;
}
ret = recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client, &len);
if(ret < 0)
{
printf("reciving error\n");
}
printf("recving data from %s: %s\n", inet_ntoa(client.sin_addr), buf);
snprintf(buf, sizeof(buf), "server:");
ret = sendto(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client, sizeof(client));
if(ret < 0)
{
printf("send error\n");
return -1;
}
close(socket_fd);
return 0;
}
client
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int socket_fd;
struct sockaddr_in server;
int ret;
char buf[255] = "send to server";
int len = sizeof(struct sockaddr_in);
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_fd < 0)
{
printf("socket error\n");
}
server.sin_family = AF_INET;
server.sin_port = htons(5900);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = sendto(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&server, sizeof(server));
if(ret < 0)
{
printf("sendto error\n");
return -1;
}
ret = recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&server, &len);
if(ret < 0)
{
printf("error recv from\n");
return -1;
}
printf("recving from server:%s: %s\n", inet_ntoa(server.sin_addr), buf);
close(socket_fd);
}
Read the code above and you will find the answer to your question
I've can't seem to figure out how to send and receive data between my existing sockets. right now I am just trying to send one string back and forth and be able to see it. Any help as to what i am doing wrong would be greatly appreciated.
the problem parts are here:
char hostm[10];
printw("you are host!\n");
printw("Type the number you would like to pick %s: ", req.hostname);//gets row1
scanw("%s", &hostm);
printw("%s\n", hostm);
write( (struct sockaddr *)&req.sa, &hostm, sizeof(hostm));
char response[80];
read( (struct sockaddr *)&resp.sa, &response, sizeof(response));
printw("Response: %s\n", response);
recvfrom(sock, (void *)&resp, sizeof (matchrequest), 0, (struct sockaddr *)&sa, &fromlen);
and
char response[80];
char response2[80];
read( (struct sockaddr *) &host.sa, &response, sizeof(response));
read( (struct sockaddr *) &req.sa, &response2, sizeof(response2));
printf("\n\nresponse was %s\n%s\n", &response, &response2);
write( (struct sockaddr *) &req.sa, &response, sizeof(response));
write((struct sockaddr *) &host.sa, &response2, sizeof(response2));
I don't know if its in the right place either, so here is all the code:
peer.c
#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "match.h"
int sock;
struct sockaddr_in serveraddr;
matchrequest req;
int matched = 0;
void *thread_start(void *args) {
int bytes_sent;
while(!matched) {
printf("waiting for peers...\n");
bytes_sent = sendto(sock, &req, sizeof(matchrequest), 0,(struct sockaddr*)&serveraddr, sizeof serveraddr);
if (bytes_sent < 0) {
printf("Error sending packet: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
sleep(3);
}
}
void writeResponse(char * response) {
write(sock, &response, sizeof(response));
}
int main(int argc, char *argv[])
{
pthread_t th;
struct sockaddr_in sa;
matchrequest resp;
ssize_t recsize;
socklen_t fromlen;
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (argc != 3) {
printf("specify name and game type for this peer!\n");
return;
}
req.gametype = atoi(argv[2]);
req.state = 0;
strncpy(req.peername, argv[1], 100);
printf("using name: %s\n", req.peername);
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = 0;
if (-1 == bind(sock,(struct sockaddr *) &sa, sizeof(sa)))
{
perror("error bind failed");
close(sock);
exit(EXIT_FAILURE);
}
memset(&serveraddr, 0, sizeof serveraddr);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddr.sin_port = htons(7652);
pthread_create(&th, NULL, &thread_start, NULL);
for (;;)
{
fromlen = sizeof(sa);
recsize = recvfrom(sock, (void *)&resp, sizeof (matchrequest), 0, (struct sockaddr *)&sa, &fromlen);
if (recsize < 0) {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (recsize != sizeof(matchrequest)) {
fprintf(stderr, "invalid datagram received");
continue;
}
initscr();
printw("matched with peer %s. Game can start!\n", resp.peername);
if(strcmp(resp.hostname, req.peername) == 0)
{
char hostm[10];
printw("you are host!\n");
printw("Type the number you would like to pick %s: ", req.hostname);//gets row1
scanw("%s", &hostm);
printw("%s\n", hostm);
write( (struct sockaddr *)&req.sa, &hostm, sizeof(hostm));
char response[80];
read( (struct sockaddr *)&resp.sa, &response, sizeof(response));
printw("Response: %s\n", response);
recvfrom(sock, (void *)&resp, sizeof (matchrequest), 0, (struct sockaddr *)&sa, &fromlen);
}
else
{
char peerm[10];
printw("you are peer!\n");
printw("Type the number you would like to pick %s: ", req.peername);//gets row1
scanw("%s", &peerm);
printw("%s\n", &peerm);
// send to client, transmitted fine
write(sock, &peerm, sizeof(peerm));
char response[80];
read(sock, &response, sizeof(response));
// Prints the missing character symbol, and 'random' letters
printw("Response: %s\n", response);
}
endwin();
}
close(sock); /* close the socket */
return 0;
}
matchd.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "match.h"
#define MAX_REQUESTS 100
matchrequest ready[MAX_REQUESTS];
int outsock;
void handlerequest(struct sockaddr_in sa, matchrequest req) {
matchrequest host;
int idx = req.gametype % MAX_REQUESTS;
req.state = READY;
req.sa = sa;
printf("%s on %s:%d requested game type %d \n", req.peername, inet_ntoa(req.sa.sin_addr), req.sa.sin_port, req.gametype);
// if room, place in ready position
if (strncmp(ready[idx].peername, req.peername, 100) == 0) {
// peer is just checking in
} else if (ready[idx].state == MATCHED) {
ready[idx] = req;
printf("%s selected as host. waiting for peers...\n", req.peername);
strcpy(req.hostname, req.peername);
} else {
// match with existing peer
printf("%s matched with existing host\n", req.peername);
req.state = MATCHED;
host = ready[idx];
host.state = HOST;
ready[idx] = req;
strcpy(req.hostname, host.peername);
req.peermove = req.hostmove;
req.hostmove = req.peermove;
char response[80];
char response2[80];
read( (struct sockaddr *) &host.sa, &response, sizeof(response));
read( (struct sockaddr *) &req.sa, &response2, sizeof(response2));
printf("\n\nresponse was %s\n%s\n", &response, &response2);
write( (struct sockaddr *) &req.sa, &response, sizeof(response));
write((struct sockaddr *) &host.sa, &response2, sizeof(response2));
// read(outsock, &response, sizeof(response));
// printf("\n\nresponse was %s\n\n", &response);
// write(outsock, &response, sizeof(response));
printf("sending response to %s at %s:%d\n", host.peername, inet_ntoa(host.sa.sin_addr), host.sa.sin_port);
sendto(outsock, (void *) &req, sizeof(matchrequest), 0, (struct sockaddr *) &host.sa, sizeof(host.sa));
printf("sending response to %s at %s:%d\n", req.peername, inet_ntoa(req.sa.sin_addr), req.sa.sin_port);
sendto(outsock, (void *) &host, sizeof(matchrequest), 0, (struct sockaddr *) &req.sa, sizeof(req.sa));
fprintf(stderr, "%s\n", strerror(errno));
}
}
int main(void)
{
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in sa;
matchrequest req;
ssize_t recsize;
socklen_t fromlen;
outsock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(7652);
if (-1 == bind(sock,(struct sockaddr *)&sa, sizeof(sa)))
{
perror("error bind failed");
close(sock);
exit(EXIT_FAILURE);
}
for (;;)
{
fromlen = sizeof(sa);
printf ("receiving....\n");
recsize = recvfrom(sock, (void *)&req, sizeof (matchrequest), 0, (struct sockaddr *)&sa, &fromlen);
if (recsize < 0) {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (recsize != sizeof(matchrequest)) {
fprintf(stderr, "invalid datagram received");
continue;
}
handlerequest(sa, req);
}
}
match.h
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef enum matchstate {MATCHED = 0, READY, HOST} matchstate;
typedef struct matchrequest {
matchstate state;
int gametype;
char board[4][4];
char covboard[4][4];
int player1pts;
int player2pts;
int gameover;
int turn;
int hostmove;
int peermove;
char peername[100];
char hostname[100];
struct sockaddr_in sa;
} matchrequest;
I think the problem is that read and write expect file descriptors as the first argument, but you're providing something else entirely. See the documentation for write and note that you're not calling it the way you should be. Also, I didn't read all of your code but it appears as though it would generate a lot of warnings that you shouldn't ignore.
Also note, that read may return prematurely or it may block while it waits for more data to arrive. You have to cater for these situations yourself.
Also, keep in mind that with UDP, there is no guarantee or acknowledgement of delivery of data, unlike TCP. So although your program has sent the data, it may be lost in transmission to the clients.