I am writing a C software to interface with a motorcontroller over UDP.
I'm using:
Win 7 Pro 64-Bit
eclipse luna
minGW
At the moment I have a problem, that seems to be socket/wsa related:
the execution of my program gets stuck on the recvfrom() forever (so obviously the controller doesn't respond as expected).
With the attached software this only happens on the first execution (or after not executing for ca. 3 mins) other programs had this problem 3-4 times in a row.
A look into wireshark revealed, that the first (or after 3min pause) leads to the transmission of an "ARP" package instead of my UDP message.
Why is that (it seems to be searching for the destination)? How can I avoid "crashing" my software due to this?
Did I forget to initialise anything?
My code looks like this:
#include <stdio.h>
#include <conio.h>
#include <winsock2.h>
#define Y_AXIS_IP "XXX.XXX.XXX.XX"
#define Y_AXIS_PORT 880X
int startWinsock(void);
int main() {
//Start the winsocket (needed to create sockets)
long ws = startWinsock();
if (ws) {
printf("ERROR: Failed to init Winsock API! Code: %ld\n", ws);
getch();
exit(EXIT_FAILURE);
}
//Create an UDP Socket
SOCKET UDPsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (UDPsocket == INVALID_SOCKET) {
printf("ERROR: Socket could not be created! Code: %d\n",
WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
//Create a struct to use with the socket (this gives information about type (AF_INET = Internet Protocol) which port and which IP to use)
SOCKADDR_IN addrY;
memset(&addrY, 0, sizeof(addrY));
addrY.sin_family = AF_INET; //Assert Type
addrY.sin_port = htons(Y_AXIS_PORT); //Assert Port
addrY.sin_addr.S_un.S_addr = inet_addr(Y_AXIS_IP); //assert IP Address
char message[] = "0000MTX 00000000OR:1:000F\r";
int buffersize = 100;
char *recvbuf = malloc(buffersize); //None of the replys can get larger than 100 chars
if (recvbuf == NULL) {
printf("Out of memory!\n");
getch();
exit(EXIT_FAILURE);
}
//clear the receive buffer and prepare the address size
memset(recvbuf, '\0', buffersize);
int addrsize = sizeof(addrY);
//Send the message to the device
if (sendto(UDPsocket, message, strlen(message), 0,
(struct sockaddr *) &addrY, sizeof(addrY)) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d", WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
//Receive from device (blocks program until recv event)
if (recvfrom(UDPsocket, recvbuf, buffersize, 0, (struct sockaddr *) &addrY,
&addrsize) == SOCKET_ERROR) {
//If not timed out Display the Error
printf("recvfrom() failed with error code : %d", WSAGetLastError());
getch();
exit(EXIT_FAILURE);
}
printf("%s\n", recvbuf);
getch();
free(recvbuf);
return 0;
}
int startWinsock(void) {
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 2), &wsa);
}
I would be really happy, if you had any ideas or suggestions. Thanks alot in advance!
Before a computer can send a packet to another host, it has to resolve its MAC address. This is done via an ARP request. It is handled by the operating system transparently.
recvfrom will block. It is not a bug. There are basically three ways of avoiding recvfrom from blocking forever when there is no incomming data:
make the socket asynchronous, i.e. nonblocking
set a timeout (see Set timeout for winsock recvfrom)
use select (Setting winsock select timeout accurately)
So finally I found a way to deal with this issue:
1. catch the timeout that occurs at recvfrom
2. save the sockets address in a temporary socket
3. close the original socket
4. end the WSA (call WSACleanup())
5. start the WSA (call WSAStartup())
6. create a new socket at the address of the former socket
7. transmit the message again
seems to work fine (also see code below)
If you see anything wrong or dangerous with my code, please feel free to comment and help my to improve my skills.
Thank you for your help and ideas,
Sebastian
Code:
if (recvfrom(*UDPsocket, buffer, buffersize, 0, (struct sockaddr *) &addr,
&addrsize) == SOCKET_ERROR) {
int WSAerror = WSAGetLastError();
if (WSAerror == 10060) {
printf("[WARNING] recvfrom() timed out!\n");
//Store the address of the socket
SOCKET *tempsocket = NULL;
tempsocket = UDPsocket;
//destroy the old socket
closesocket(*UDPsocket);
WSACleanup();
//create a new socket
startWinsock();
*tempsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//Send the message to the device
if (sendto(*tempsocket, Frame.pcompletemsg,
strlen(Frame.pcompletemsg), 0, (struct sockaddr *) &addr,
sizeof(addr)) == SOCKET_ERROR) {
printf("[ERROR] sendto() failed with error code : %d\n",
WSAGetLastError());
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
if (recvfrom(*tempsocket, buffer, buffersize, 0,
(struct sockaddr *) &addr, &addrsize) == SOCKET_ERROR) {
int WSAerror = WSAGetLastError();
printf("[ERROR] recvfrom() failed with error code : %d",
WSAerror);
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
} else {
printf("[ERROR] recvfrom() failed with error code : %d", WSAerror);
getch();
WSACleanup();
exit(EXIT_FAILURE);
}
}
Related
I'm a beginner and trying to set up a TCP-client for the first time, using winsock. I put together a minimal client using some bits of code I found in examples (see below). It's basically working, i.e. I can receive the server's messages, and sending messages gives the expected results.
However, unless I add a loop which constantly does a receive/send routine (or even just the receive part) the connection is closed immediately after it has been established. Can I do something to keep the connection open and only receive or send something when there is demand for it?
The server is a closed source piece of software, so I have no idea about how it is set up.
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
int startWinsock(void) {
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 2), &wsa);
}
int main(void) {
long rc;
SOCKET s;
SOCKADDR_IN addr;
printf("Starting Winsock... ");
rc = startWinsock();
if (rc != 0) {
printf("Error: unable to start Winsock, error code: %d\n", rc);
}
else {
printf("done.\n");
}
printf("Creating socket... ");
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
printf("Error: Unable to create socket, error code: %d\n", WSAGetLastError());
}
else {
printf("done.\n");
}
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(10134);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
if (rc == SOCKET_ERROR) {
printf("Connection failed, error code: %d\n", WSAGetLastError());
}
else {
printf("Connected to 127.0.0.1.\n");
}
//if I add a loop here, which receives and/or sends stuff constantly, the connection stays established
return 0;
}
Very simple:
Your client tries to connect to the server.
If it succeeds, send a command, and read the response.
Keep receiving and sending until you're "done", then close the socket.
In other words:
You have control over when to close the connection - the socket will stay open until you close it.
Essentially, you're inventing your own custom network protocol
STRONG SUGGESTION:
Review Beej's Guide to Network Programming
I'm making a LiDAR project for university but I got stuck a little bit. I am sending a package which includes the exact position of the motor and the distance read from the distance sensor through WiFi and the package should look like this "position/distance". I made a client program in Visual Studio but when I receive the package I have iiiiii at the end of the message and the packages are not coming through in the right order. I am gonna put the code here and if you have any idea of what I am missing I would appreciate it a lot.
#include <iostream>
#include <stdio.h>
#include <string.h>
#include "winsock2.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
FILE* file;
file = fopen("package.txt", "w");
if (file == NULL) {
printf("Error openning the file\n");
exit(1);
}
int iResult;
WSADATA wsaData;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
printf("Error WSAStartup\n");
SOCKET ClientSocket;
ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ClientSocket == INVALID_SOCKET)
{
printf("Error initializing socket with the next error code: %ld\n",
WSAGetLastError());
WSACleanup();
return 0;
}
int Port = 13000;
char IP[14] = "192.168.0.105";
sockaddr_in ServerAddr;
int AddrLen = sizeof(ServerAddr);
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = inet_addr(IP);
ServerAddr.sin_port = htons(Port);
if (connect(ClientSocket, (SOCKADDR*)&ServerAddr, AddrLen) == SOCKET_ERROR)
{
printf("Error connecting with the next error code: %ld\n",
WSAGetLastError());
WSACleanup();
return 0;
}
else {
printf("Sikeres kapcsolodas\n");
}
char message[15];
int receiving = 0;
while (receiving != SOCKET_ERROR) {
receiving = recv(ClientSocket, message, sizeof(message), 0);
fprintf(file, "%s\n", message);
printf("%i, %i\n", receiving, sizeof(message));
}
if (receiving == SOCKET_ERROR) {
printf("Error at receiving the message\n");
closesocket(ClientSocket);
WSACleanup();
return 0;
}
fclose(file);
return 0;
}
The message that I get looks like this:
0.00/176.00ÌÌÌÌÌÌÌÌÌÌÌÌÌ
0.75/180.003.75ÌÌÌÌÌÌÌÌÌ
/179.008.63/179ÌÌÌÌÌÌÌÌÌ
.009.008.63/179ÌÌÌÌÌÌÌÌÌ
14.06/179.0019.ÌÌÌÌÌÌÌÌÌ
13/178.00.0019.ÌÌÌÌÌÌÌÌÌ
24.19/178.0019.ÌÌÌÌÌÌÌÌÌ
29.44/179.0019.ÌÌÌÌÌÌÌÌÌ
35.06/178.0019.ÌÌÌÌÌÌÌÌÌ
39.94/180.0045.ÌÌÌÌÌÌÌÌÌ
19/178.00.0045.ÌÌÌÌÌÌÌÌÌ
50.44/180.0045.ÌÌÌÌÌÌÌÌÌ
55.69/179.0061.ÌÌÌÌÌÌÌÌÌ
50/179.00.0061.ÌÌÌÌÌÌÌÌÌ
66.19/180.0072.ÌÌÌÌÌÌÌÌÌ
38/178.00.0072.ÌÌÌÌÌÌÌÌÌ
77.63/178.0083.ÌÌÌÌÌÌÌÌÌ
25/178.00.0083.ÌÌÌÌÌÌÌÌÌ
88.13/178.0093.ÌÌÌÌÌÌÌÌÌ
56/176.00.0093.ÌÌÌÌÌÌÌÌÌ
99.19/177.0093.ÌÌÌÌÌÌÌÌÌ
104.44/177.0011ÌÌÌÌÌÌÌÌÌ
0.25/176.000011ÌÌÌÌÌÌÌÌÌ
115.31/177.0011ÌÌÌÌÌÌÌÌÌ
121.13/177.0011ÌÌÌÌÌÌÌÌÌ
126.75/173.0013ÌÌÌÌÌÌÌÌÌ
2.19/176.00136.ÌÌÌÌÌÌÌÌÌ
88/176.0000136.ÌÌÌÌÌÌÌÌÌ
142.69/176.0014ÌÌÌÌÌÌÌÌÌ
8.31/177.000014ÌÌÌÌÌÌÌÌÌ
153.75/177.0014ÌÌÌÌÌÌÌÌÌ
159.38/174.0016ÌÌÌÌÌÌÌÌÌ
5.38/173.000016ÌÌÌÌÌÌÌÌÌ
170.63/174.0017ÌÌÌÌÌÌÌÌÌ
5.88/169.000017ÌÌÌÌÌÌÌÌÌ
181.13/169.0018ÌÌÌÌÌÌÌÌÌ
7.13/169.000018ÌÌÌÌÌÌÌÌÌ
192.56/167.0019ÌÌÌÌÌÌÌÌÌ
8.38/170.000019ÌÌÌÌÌÌÌÌÌ
203.81/168.0019ÌÌÌÌÌÌÌÌÌ
209.25/166.0021ÌÌÌÌÌÌÌÌÌ
4.88/165.000021ÌÌÌÌÌÌÌÌÌ
220.69/168.0021ÌÌÌÌÌÌÌÌÌ
226.13/167.0023ÌÌÌÌÌÌÌÌÌ
1.94/167.000023ÌÌÌÌÌÌÌÌÌ
237.56/167.0024ÌÌÌÌÌÌÌÌÌ
3.38/166.000024ÌÌÌÌÌÌÌÌÌ
248.81/169.0025ÌÌÌÌÌÌÌÌÌ
4.25/169.00259.ÌÌÌÌÌÌÌÌÌ
88/170.00265.69ÌÌÌÌÌÌÌÌÌ
/170.00271.31/1ÌÌÌÌÌÌÌÌÌ
69.0000271.31/1ÌÌÌÌÌÌÌÌÌ
277.50/170.0028ÌÌÌÌÌÌÌÌÌ
Note: it should look like ex. 241.00/32.00, position expressed in degree and distance in mm.
In this line:
receiving = recv(ClientSocket, message, sizeof(message), 0);
receiving is set to the number of bytes actually received.
It is not necessarily the size of the buffer you pass in (in your case it is a few bytes less).
But when you dump it th the file in this line:
fprintf(file, "%s\n", message);
You ignore the number of bytes received.
Using with fprintf with "%s" requires a zero terminated array of characters, and resv does not add the zero termination.
You can solve this issue by adding this line before the fprintf:
message[receiving] = '\0';
Another issue is the maximum number of bytes recv is allowed to fill.
Since we want to keep one byte for the zero termination, the call to recv should be:
receiving = recv(ClientSocket, message, sizeof(message)-1, 0);
I.e. allow receive fill only sizeof(message)-1 bytes and keep one for the zero termination.
I wanted to receive an *.xml data by port 3702.
So I made a example Server. And sended data by three port 1500,2500,3702.(Edit the PORT in line 43)
It worked and printed data correctly from port 1500,2500.
But when I set the PORT to 3702.
it returned me a error:**Bind failed with error code :10048**
I found that maybe it existed other Client IP were sending data by PORT 3702 in my LAN.
How can I fix it?
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define BUFLEN 8192 //Max length of buffer
#define PORT 3702 //The port on which to listen for incoming data
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen, recv_len;
char buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other);
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
//Bind
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//keep listening for data
while (1)
{
printf("Waiting for data...");
fflush(stdout);
//clear the buffer by filling null, it might have previously received data
memset(buf, '\0', BUFLEN);
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
//exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n", buf);
//now reply the client with the same data
}
closesocket(s);
WSACleanup();
return 0;
}
This is due to Address already in use.
Typically, only one usage of each socket address (protocol/IP address/port) is permitted. This error occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that was not closed properly, or one that is still in the process of closing. For server applications that need to bind multiple sockets to the same port number, consider using setsockopt (SO_REUSEADDR).
Client applications usually need not call bind at all - connect chooses an unused port automatically. When bind is called with a wildcard address (involving ADDR_ANY), a WSAEADDRINUSE error could be delayed until the specific address is committed. This could happen with a call to another function later, including connect, listen, WSAConnect, or WSAJoinLeaf.
I'm trying to send a UDP packet to a router with a time to live of 1, to then receive an ICMP time exceeded reply. So far I'm able to send the packet, but when my program gets to the recv part of the execution, it just hangs. I have an error check for recvfrom, but it doesn't even get to that. My computer is receiving the request. I know this because I run Wireshark when I run the program and I filter for ICMP requests. Every time I run the program, I receive the reply. What am I doing wrong with recvfrom?
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#define UNSPEC_PROTO 0
int main(int argc, const char *argv[])
{
if (argc != 2) {
printf("usage: routetracer <ip address or hostname>\n");
return -1;
}
struct addrinfo hints; //params for ret val of getaddrinfo
struct addrinfo* ret; //return value of getaddrinfo
struct sockaddr* reply_addr;
char ipv4[INET_ADDRSTRLEN];
char* msg = "THE PORT IS OVER 9000!!!!";
int status = 0;
int ttl = 0;
int src_sock = 0;
int recv_sock = 0;
socklen_t reply_addr_len = sizeof(struct sockaddr);
const char* dest_port = "9001";
int icmp_msg_len = 100;
char icmp_msg[icmp_msg_len];
//define what we want from getaddrinfo
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_DGRAM; //UDP packets
//call getaddrinfo to fill ret, w/ error chk
if ((status = getaddrinfo(argv[1], dest_port, &hints, &ret)) != 0) {
printf("getaddrinfo: %s\n", gai_strerror(status));
return -1;
}
//extract IPv4 address from ret
struct sockaddr_in* ip = (struct sockaddr_in *)ret->ai_addr;
//convert address from pure numbers to something easier to read
inet_ntop(ret->ai_family, &(ip->sin_addr), ipv4, INET_ADDRSTRLEN);
//kindly inform the user of which hostname they are connecting to
printf("Route for: %s\n", ipv4);
//create a socket for our machine
if ((src_sock = socket(ret->ai_family, ret->ai_socktype,
ret->ai_protocol)) < 0) {
fprintf(stderr, "Error creating host socket: %s\n", strerror(errno));
return -1;
}
//create a socket to recv icmp packet from hops
if ((recv_sock = socket(AF_INET, SOCK_DGRAM, UNSPEC_PROTO)) < 0){
fprintf(stderr, "Error creating recv socket: %s\n", strerror(errno));
}
/*
* We go from hop to hop by incrementing the time to live in the IP header
* for each hop we visit until we reach the destination IP address (which we
* already have). Time to live decrements for every hop, so once it reaches
* zero we report the IP address of the node we are connected to.
*/
//while(test_ip != dest_ip)
//time_to_live++
//send_to(dest_addr)
//receive icmp error message
//get src addr of error msg from ip header of icmp
//test_ip = src addr
/*
while (last_hop == 0) {
ttl++;
setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
sendto(sock, msg, strlen(msg), 0, (struct sockaddr *)ip, sizeof(ip));
}
*/
ttl = 1;
if (!(setsockopt(src_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)))) {
printf("TTL set successfully\n");
} else {
printf("Error setting TTL: %s\n", strerror(errno));
}
if ((sendto(src_sock, msg, strlen(msg), 0, ret->ai_addr,
ret->ai_addrlen)) > 0) {
printf("msg sent successfully\n");
} else {
fprintf(stderr, "Error sending msg: %s\n", strerror(errno));
}
if ((recvfrom(recv_sock, icmp_msg, icmp_msg_len, 0, reply_addr,
&reply_addr_len)) != -1) {
/* PROCESS THE INFORMATION */
printf("Packet received\n");
} else {
fprintf(stderr, "Error receiving packet: %s\n", strerror(errno));
}
return 0;
}
Normally, UDP pretty much ignores ICMP errors, so if you want to see them, you need to open a raw socket to receive all ICMP packets and look for ones relevant to your socket.
On Linux, at least, an alternative is to set the IP_RECVERR socket option. If you do that, you can do a recvmsg with the MSG_ERRQUEUE flag set to get any ICMP (or other) errors associated with your socket. This has the advantage of not requiring elevated privileges or a second socket.
In some implementations of sockets, UDP socket has to be connected to receive errors.
So, you need to add connect call and then use send/recv functions.
I've confirmed this on FreeBSD. At least one source clearly states that:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-5.html (see 5.3 Does doing a connect() call affect the receive behaviourof the socket?)
P.S. Note, however, that you won't receive exact ICMP error message that way. You'll only get some error code, without many details (if any).
Check the options when you are opening your sockets.
See How to sniff all ICMP packets using RAW sockets.
See How to receive ICMP request in C with raw sockets.
You may also want to change the socket options to be non-blocking and use the select() function to determine if there is something to read or not.
For examples on using the select() function see the following.
Blocking recvfrom with select system call.
Unexepcted results with select and recvfrom.
First of all, your code has undefined behavior, because reply_addr is uninitialised. You should fix that first:
struct sockaddr_in reply_addr;
...then:
recvfrom(recv_sock, icmp_msg, icmp_msg_len, 0, (struct sockaddr*)&reply_addr,
&reply_addr_len);
Finally, you need to use raw sockets, not datagram sockets, to receive ICMP packets:
recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
I'm a newbie in Network Programming, started to learn how to use WinSock in C.
I don't have any knowledge in Networking right now.
Anyway, I've written the following code for Client and Server, using WinSock.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define MY_ERROR 1
#define PORT 7777
#define MAX_NUM_CLIENTS 1 /* I don't know how to thread right now. */
#define MAX_CLIENT_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket, acceptSocket;
struct sockaddr_in server, client;
int sockAddrInLength = sizeof(struct sockaddr_in);
char clientMessage[MAX_CLIENT_MSG_LEN];
int clientMessageLength;
char* message;
int running = 1;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
return MY_ERROR;
}
printf("WSAStartup succeded.\n");
mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
return MY_ERROR;
}
printf("Socket creation succeeded.\n");
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (bind(mySocket, (struct sockaddr*) &server, sizeof server) == SOCKET_ERROR)
{
fprintf(stderr, "Binding socket on port %d failed.\n", PORT);
return MY_ERROR;
}
printf("Binding socket on port %d successfully.\n", PORT);
while (running)
{
listen(mySocket, MAX_NUM_CLIENTS);
printf("Waiting for a connection...\n");
acceptSocket = accept(mySocket, (struct sockaddr*) &client, &sockAddrInLength);
if (acceptSocket == INVALID_SOCKET)
{
fprintf(stderr, "Accept failed.\n");
return MY_ERROR;
}
printf("Accept succeeded.\n");
if ((clientMessageLength = recv(acceptSocket, clientMessage, sizeof clientMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
clientMessage[clientMessageLength] = NULL; /* Null terminator */
printf("Client: %s\n", clientMessage);
message = "Hello client, I'm the server. Bye bye. :-)\n";
if (send(acceptSocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Send failed.\n");
return MY_ERROR;
}
printf("Send succeded.\n");
}
closesocket(mySocket);
WSACleanup();
getchar();
return 0;
}
And this is the code for the Client:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP /* My IP */
#define MY_ERROR 1
#define PORT 7777
#define MAX_SERVER_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket;
struct sockaddr_in server;
char* message;
char serverMessage[MAX_SERVER_MSG_LEN];
int serverMessageLength;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
getchar();
return MY_ERROR;
}
printf("WSASucceeded.\n");
mySocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
getchar();
return MY_ERROR;
}
server.sin_addr.s_addr = inet_addr(IP);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (connect(mySocket, (struct sockaddr*) &server, sizeof server) < 0)
{
fprintf(stderr, "Connection failed. error: %s\n",WSAGetLastError());
getchar();
return MY_ERROR;
}
printf("Connection established.\n");
message = "Hello server, I'm the sweet client. :-)\n";
if (send(mySocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Sending failed.\n");
return MY_ERROR;
}
printf("Sending succeeded.\n");
if ((serverMessageLength = recv(mySocket, serverMessage, sizeof serverMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
serverMessage[serverMessageLength] = NULL;
printf("Server: %s", serverMessage);
closesocket(mySocket);
getchar();
return 0;
}
Ok.
When I run both server and client on my comupter, and define IP (in the client code) to be my internal IP (I think, becuase it is the form of 192.168.x.x) it works fine.
When I define IP to be my external IP, it doesn't work on my computer (when I run both program in my computer). The connection failes.
In addition -
When I'm trying to run the client on any other computer, it doesn't work (when IP is defined to be my internal or my external IP), the connection failes.
My questions are:
Why when I run both server & client on my computer, it works just with my internal IP?
What should I do in order that the client could be run on another computer and it will work?
I know that maybe the answer contains terms like "internal/external IPs", "routers", maybe "firewall" or "port forwarding".
Just remember I'm really a newbie in Networking and I don't have any knowledge about those terms, so please: I hope your explnations will be beginner-friendly.
I want to start learning Networking, but my first step is to understand how to use Sockets, and I have a problem in the connetction with other computers.
If you have any articles/something like that in order to give me a better understanding of the problem, it could help too.
Thank you very much! :)
This doesn't look like a coding problem, but a network configuration problem.
Let me try and rephrase what you're saying : Please correct me if I've misunderstood:-
You have an "internal" network (192.168.x.y).
You run the client on one PC on your internal network, and the server on another.
It all works so far.
But, you're also connected to the internet, via a different 'external' IP address
- When your client tries to access the server via this address, it fails. (The exact error code from WSAGetLastError is useful here, please)
At this point, it's down to how you're connected to the net. Let's assume a typical home office scenario. You have broadband, with an ADSL router/modem giving you network connectivity. Now, while the router will have an 'external' IP address, PC's on your local network typically do NOT. So, if you try connecting to the 'external' IP, you're actually trying to talk to the router.
This is where Port forwarding comes into play. You need to configure the router to forward port 7777 to the correct IP address for your server on the internal network. You'll find a screen like this on your router somewhere.
You would enter port 7777 for both 'from' and 'to', enable TCP, and specify the LAN address of your server. The router will then forward incoming connections on port 7777 to the specified server.