I am performing communication between client(windows) and server(linux RT) in c. I have written a client code for windows operating system (one laptop) and server code for linux operating system (another laptop). I am connecting the both laptop via ethernet cable and configured them on the same subnet.
SERVER.c : Linux
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
else
printf("Server : Socket() successful\n");
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
err("bind");
else
printf("Server : bind() successful\n");
while(1)
{
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr,
&slen)==-1)
err("recvfrom()");
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
}
close(sockfd);
return 0;
}
CLIENT.c - windows
#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <winsock.h>
#include <io.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
WORD wVersionRequested;
WSADATA wsaData;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
if (WSAStartup (wVersionRequested, &wsaData) != 0){
printf("Winsock initialised failed \n");
} else {
printf("Initialised\n");
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(argv[1], &serv_addr.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
while(1)
{
printf("\nEnter data to send(Type exit and press enter to exit) : ");
scanf("%[^\n]",buf);
getchar();
if(strcmp(buf,"exit") == 0)
exit(0);
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
err("sendto()");
}
close(sockfd);
return 0;
}
My question :
Is it possible to perform communication like this ??
Do I want to take specific measures for doing this ??
Please give ideas regarding this ?
You can connect two systems directly (via ethernet cable), but typically you must use a special cable for that: it is called a "crossover cable". Otherwise no connection is possible.
Newer network controllers implement a detection for this kind of setup, so it might be possible to use a standard cable for this setup, but this depends on the network controllers build into the two systems. You will have to try or consult the documentation.
Also it migh be that you have to select some special configuration on the MS-Windows side (inside the network adapter configuration) for this to work. I experienced communication problems with the standard setup a few times. You can consult google for those settings.
Related
How come this client is only able to read data sent from the first server write system call ? It correctly reads the data sent by the first write, but not with the second one...
Here's the client :
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 1025
#define SA struct sockaddr
int main(){
int sockfd;
struct sockaddr_in servaddr, cli;
//CREATE SOCKET
sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
char buff[1024];
while( (read(sockfd, buff,sizeof(buff))) > 0){
printf("%s\n",buff);
}
close(sockfd);
return 0;
}
And here is the server :
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SA struct sockaddr
#define PORT 1025
int main(){
int sockfd, connfd;
unsigned int len;
struct sockaddr_in servaddr, cli;
//SOCKET CREATION
sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
//BIND
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
//LISTEN
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
for(;;){
len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server accept failed...\n");
exit(0);
}
char buff[]="Hi";
char buff2[]="More data sent..\n";
write(connfd,buff,sizeof(buff)); //work
write(connfd,buff2,sizeof(buff2)); //doesn't work
close(connfd);
}
return 0;
}
I also noticed it works if I put the second write inside a loop that requires a certain amount of time. For example :
long max=0;
while(max<1000000000){
//second write works
write(......);
}
Could someone give an explanation of why write behaves like that and what's going on under the hood ?
I've been a Unix programmer for a decent amount of time, and I know pretty well the system's socket API, I use it mostly for networking.
The thing is that I'm currently trying to create a cross-platform software, and so I began to learn how to compile my source code into windows executable files.
I've created a startup() function which does the simplest thing: connect to a server (of which IP is given), and return -1 on failure. On Linux my code runs smooth, but on Windows(7) I get the same error on some machines - "Connect()" function failed, errno: "Result too large" which (by what I understood) means it could no find any listening server on that IP, but on others it runs well.
Here is the code (win version):
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
int startup(struct sockaddr_in sin)
{
int sockfd, soaddr;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
fprintf(stderr, "socket:%s\n", strerror(errno));
return(-1);
}
soaddr = sizeof(sin);
if(connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", strerror(errno));
return(-1);
}
return sockfd;
}
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
sockfd = startup(sin);
// Code continues
return(0);
}
note:ADDR has been changed for privacy reasons, but there is a working server on that machine
So, why exactly am I getting this error ?
WinSock does not use errno, it uses WSAGetLastError() instead.
WinSock does not use file descriptors for sockets, it uses actual kernel objects. On Windows, you need to use the SOCKET handle type, not int, for your socket variables (or at least type-cast SOCKET values to (u)intptr_t and then type-cast back to SOCKET when calling WinSock functions).
You can use the Win32 API FormatMessage() function to get a human readable string for a WinSock error code.
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
__declspec(thread) char errmsg[256];
char* sockerr(int errcode)
{
DWORD len = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, 0, errmsg, 255, NULL);
if (len != 0)
errmsg[len] = 0;
else
sprintf(errmsg, "error %d", errcode);
return errmsg;
}
int startup()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(1,1), &wsaData);
if (ret != 0) {
fprintf(stderr, "WSAStartup:%s\n", sockerr(ret));
return(ret);
}
return(0);
}
void cleanup()
{
WSACleanup();
}
SOCKET connectToServer(struct sockaddr_in sin)
{
SOCKET sockfd;
int soaddr;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == INVALID_SOCKET)
{
fprintf(stderr, "socket:%s\n", sockerr(WSAGetLastError()));
return(INVALID_SOCKET);
}
soaddr = sizeof(sin);
if (connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", sockerr(WSAGetLastError()));
closesocket(sockfd);
return(INVALID_SOCKET);
}
return(sockfd);
}
int main(int argc, char *argv[])
{
SOCKET sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
if (startup() != 0) {
exit(1);
}
sockfd = connectToServer(sin);
if (sockfd != INVALID_SOCKET)
{
// ...
closesocket(sockfd);
}
cleanup();
return(0);
}
You will have to take these differences into consideration when writing cross-platform socket code.
According to your code you are running client socket in windows machine.You need to load runtime libraries for windows as
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
You can refer to Windows Client Socket Source. Hope this works for you.
I've successfully made an "echo client", and I'd like to add robustness before moving along to the rest of my project. Notably I'd like to view the "TCP window size" value inside the TCP header, and ensure that I don't flood the server with my next transmission.
I am not sure if this is possible without using raw sockets and forming/parsing the TCP header myself. While that isn't impossible, I'd prefer to use built in functions to access the header with my current code if possible. Please let me know if you have any suggestions.
#include "../include/a8gcc.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#define buffer_len 512
/* server address */
#define SERVER "192.168.2.115"
/* server port number */
#define SERVPORT 10001
int main(void)
{
struct sockaddr_in serv_addr;
struct hostent *server;
int sock_fd, num_read = 0;
char in_data[buffer_len];
printf("is_ethernet from GCC");
setbuf(stdout, NULL);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd < 0){
perror("Opening socket error");
exit(1);
}else{
printf("Opening the socket...OK.\n");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
server = gethostbyname(SERVER);
if(server == NULL){
printf("%s \n", h_errno);
perror("getting host address error");
exit(1);
}
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(SERVPORT);
if (connect(sock_fd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
perror("ERROR connecting");
exit(1);
}
while(1){
num_read = read(sock_fd,in_data,buffer_len);
write(sock_fd,in_data,num_read);
}
return 0;
}
I do not believe that it is possible for you to examine the actual content of the TCP/IP headers from within your code unless you are going to use raw sockets and generate the packets yourself. :( Sorry!
Let's assume there are two linux machines that are located in two different networks have the following configurations
Node1 Node2
IPaddr(private) 192.168.0.14 10.25.3.75
Router modem's IP(real) 1.2.3.4 5.6.7.8
Netmask (real) 255.255.0.0 255.255.192.0
Router modem's IP(priv) 192.168.0.1 10.0.20.1
Netmask (priv) 255.255.255.0 255.0.0.0
Here below is a generic UDP (client) socket code in C (error check is not included to save space on the question). Assume that the below could would be run on the node1. My question is that how do I need to define the node2 on the below code and what else do I need to edit so that UDP packet from node1 to node2 would be delivered without any problem?
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define SRV_IP "5.6.7.8"
int main(){
struct sockaddr_in serv_addr;
int sockfd, i, slen=sizeof(serv_addr);
char buf[512] = "hello";
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1234);
inet_aton(SRV_IP, &serv_addr.sin_addr);
sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen);
close(sockfd);
return 0;
}
I assume the UDP server part (on node2) is a generic code and does not need any specific modification to receive the packet from the node1, does it?
Routing UDP packets (as well as TCP) is not the task you should solve in your code, it is performed by routers. You should write your code as if both client and server are on the same network (your current code looks ok), BUT you should also set up your routers so that they: 1) allow routing UDP through NAT, and 2) the router for the Node2 (5.6.7.8) must forward its UDP traffic for port 1234 to the Node2's private address.
Here is a code from my college days, hope this will help
/* Sample UDP server */
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;;)
{
len = sizeof(cliaddr);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
sendto(sockfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
printf("-------------------------------------------------------\n");
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
}
and a client
/* Sample UDP client */
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
char sendline[1000];
char recvline[1000];
if (argc != 2)
{
printf("usage: udpcli <IP address>\n");
exit(1);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
servaddr.sin_port=htons(32000);
while (fgets(sendline, 10000,stdin) != NULL)
{
sendto(sockfd,sendline,strlen(sendline),0,
(struct sockaddr *)&servaddr,sizeof(servaddr));
n=recvfrom(sockfd,recvline,10000,0,NULL,NULL);
recvline[n]=0;
fputs(recvline,stdout);
}
}
I have a problem, I have a client server udp, in server side I need to access data from client side to control movement of the robot. For the experiment I use to print "oke" if the value of the data is 1.
here the code program:
#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 sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
struct hostent *he;
int addr_len, numbytes;
char dt[30];
char buf[MAXBUFLEN];
int main()
{
printf("‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐\n");
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); }
while(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);
if (buf[0]==1)
{ printf("oke\n");}
printf("Me : ");
scanf("%s", dt);
if((numbytes=sendto(sockfd,dt,strlen(dt),0,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)))==-1)
{
perror("sendto");
exit(1);
}
}
close(sockfd);
return 0;
}
when I put "1" in client side the result is:
‐‐‐‐‐ PROGRAM CHATTING ‐‐‐‐‐
130.130.66.76 : "1"
Me :
even in the program there are:
if (buf[0]==1)
{ printf("oke\n");}
why the program cannot access to inside of if?
Try if (buf[0]=='1')
Number characters map to different ASCII values than their number, so, for example, '1'==49.