I am writing a simple TCP client so that I can connect to an UR (Universal Robot) robot, and send messages (popup XXXX) to the port number 29999, to generate popup messages in the UR screen. UR server does not respond correctly to the gethostbyaddr neither gethostbyname functions when connecting, so, for testing, I connect directly to the IP and Port. The code of the simple TCP client is as follows:
int initTCPSocket(void)
{
struct in_addr ip;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("ERROR opening socket");
return -1;
}
portno = atoi(serverPort.c_str());
if (!inet_aton(serverIP.c_str(), &ip))
printf(" ERROR: error parsing IP address %s", serverIP.c_str());
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htons(ip.s_addr);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
printf("ERROR connecting to server");
return -3;
}
else
printf("Connected to server");
}
The code that actually sends data is:
bool SendDataTCP (tekniker_tcp_comms::SendDataTCP::Request &req, tekniker_tcp_comms::SendDataTCP::Response &res)
{
if (sockfd < 0)
{
ROS_INFO("ERROR in connection");
res.dataSent=false;
return true;
}
size_t msgLength = req.msg.data.length();
//write to connected server.
int n = write(sockfd, req.msg.data.c_str(),(int)msgLength);
if (n < 0)
{
ROS_INFO("ERROR writing to socket");
res.dataSent=false;
}
else
{
ROS_INFO("write %d bytes. Message %s",n, req.msg.data.c_str());
res.dataSent=true;
}
return true;
}
I obtain messages of correct connection, and I can call the Service, and the write function works ok, but, no popup appears in the UR. It seems the UR does not receive correctly the messages.
Connecting to the UR server for popup messages using ncat ( ncat 172.16.205.2 29999) and sending messages manually works fine.
After debugging for some hours, I can not find any cause for this problem. I would appreciate a lot any kind of advise,
Thank you in advance,
After inserting Wireshark to monitor TCP/IP, the problem was with the LF termination character, that was not correctly sent.
Solving this problem the client has worked correctly.
Related
I have an application that sends a GET request using winsock on port 80 using a TCP socket. A few users have reported an issue where no response is received, looking at network logs and seeing the network device is getting the data just the app isn't it was clear that the firewall was blocking it.
Having disabled the firewall it then worked fine but what I don't understand is why it was getting blocked. The connection is created from the users computer, it connects fine and sends (which I assumes automatically opens a port) so how can data be lost on the same connection when received? Should I be providing additional winsock settings? Or is there simply no way around stopping the firewall blocking an already active connection?
Here is a stripped down version of the winsock code
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return -1;
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(80);
client.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
if (connect(sock, (struct sockaddr *)&client, sizeof(client)) < 0){
closesocket(sock);
return -1;
}
if (send(sock, buffer, buflength, 0) != buflength){
closesocket(sock);
return -1;
}
//get response
response = "";
int resp_leng = BUFFERSIZE;
while (resp_leng == BUFFERSIZE)
{
resp_leng = recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng > 0)
response += std::string(buffer).substr(0, resp_leng);
else
return -1;
}
closesocket(sock);
Your while loop exits if a recv() returns less than BUFFERSIZE. This is wrong -- you must always assume that recv() can return any amount of data from 1 byte up to and including the supplied buffer size.
I've been writing a server and every time I quit it and re-open it, it seems to fail to bind to the socket. I'm connecting 2 clients and then disconnecting them with close() before I shut down the server, I also then quit the clients before opening the server just in case, however it still seems to fail and I have to restart my computer. Here is my code:
listenSocket = device = app = 0;
struct sockaddr_in server_addr;
char buffer[1024];
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, '0', sizeof(server_addr));
memset(buffer, '0', sizeof(buffer));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(35565);
//bind the socket
if (bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
NSLog(#"Error binding to socket");
}
if (listen(listenSocket, 5) == -1) {
NSLog(#"Failed to listen");
}
//launch thread for console
[NSThread detachNewThreadSelector:#selector(console) toTarget:self withObject:nil];
NSLog(#"Starting server");
//socket open, ask for clients
while (true) {
int client = -1;
if (!device || !app)
client = accept(listenSocket, (struct sockaddr*)NULL, NULL);
//handshake omitted for length
}
And the code to close the server:
close(listenSocket);
close(device);
close(app);
NSLog(#"Clean");
Is there something I'm doing wrong? Any help would be appreciated. Thanks.
EDIT: Here is my error checking code:
NSLog(#"%s",strerror(errno));
int e = bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr));
NSLog(#"%s",strerror(errno));
You need to set the SO_REUSEADDR option. Otherwise, once you grab the port in a process, there is a significant timeout before the kernel will let you have it again. Much detail to be found in an existing question; I've voted to close as a duplicate.
I had a similar problem which was caused by another process holding on to the ports. Killing that process solved the problem.
In unix, I want to make a client program connect to a server running on different machine. For this, I need to enter the ip address of server through keyboard and then pass that ip address in the connect() system call of client. I tried reading as a string, and passing it.But it didnt work. Is there any specific way to pass the ip address?
Assuming IPv4, the function you're looking for is inet_addr, which converts the string representation of an IPv4 address to a numerical value which can be passed into various socket functions:
int get_connection(const char *ip, int port)
{
int sock;
struct sockaddr_in sin;
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_port = htons(port);
if ((sock=socket(AF_INET,SOCK_STREAM,0))==-1) {
perror("Error creating socket");
return -1;
}
if (connect(sock,(struct sockaddr *)&sin,sizeof(sin))==-1) {
perror("Couldn't connect");
close(sock);
return -1;
}
return sock;
}
I have a server that receives commands from various other local processes.
I chose the most simplest form (endless loop with accept-read), but here the socket-connections remain open and I soon run out of them (running on a virtual host). Then, on a client, socket() fails with the error message "Cannot allocate memory". (However memory is not the problem, it surely is some socket-limitation from the virtual host.)
I also tried to have the whole thing (unlink-socket-bind-accept-listen-read-close) in an endless loop, which also does not solve the problem. One of these commands seems to grab a socket-connection that never gets released. (Only killing and restarting the server process allows the clients to connect again) Using shutdown() before close() also does not help.
The type of the socket is AF_UNIX / SOCK_SEQPACKET.
How can I use a socket without leaking system ressources?
Edit: As requested the endless loop in the server:
while(1)
{
unlink(SOCKET_FILE_PATH);
if((socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
{
perror("socket() failed");
return 1;
}
if(bind(socket_fd, (const struct sockaddr *) &server_address, sizeof(server_address)) < 0)
{
close(socket_fd);
perror("bind() failed");
return 1;
}
listen(socket_fd, 10);
newsockfd = accept(socket_fd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
return 1;
}
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0)
{
perror("ERROR reading from socket");
return 1;
}
printf("buffer: \"%s\"\n",buffer);
shutdown(socket_fd, SHUT_RDWR);
close(socket_fd);
}
Where do you close 'newsockfd'? Also, there is no guarantee that the buffer contains a null-terminated string, so calling printf(%s..) on it will likely segfault or some other UB.
I want to know if my server is online via my ios application. Here's what I'm doing:
Boolean result;
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFDataRef)(serverIPAddress)); //serverIPAdress = "10.10.10.100:5010"
if(hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
}
if (!result) { //This means that the host was unreachable
return ;
}
My server is online and I can access it later on in the code(meaning that my connection to the server works perfectly fine). However, I want to be able to detect if my server, on a certain port, is reachable.
Also, if I remove the ":5010" from the ip address, it detects that my server is online (it doesn't go in the "!result" condition) and detects that my server is offline if I put "10.10.10.253" which corresponds to no ip address on my network.
How can I manage to determine if my server is online or not ?
I've looked at this question : Reachability with Address - Server AND Port - iOS 5 but it doesn't work since it always return that it is reachable no matter what ip address I enter
Thanks in advance
One approach could be to open a socket connection to a specific port to see if you get any response back. If not, then the destination is unreachable. For example
#include <arpa/inet.h> //for PF_INET, SOCK_STREAM, IPPROTO_TCP etc
CFRunLoopSourceRef gSocketSource;
void ConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
UInt8 buffer[1024];
bzero(buffer, sizeof(buffer));
CFSocketNativeHandle sock = CFSocketGetNative(socket); // The native socket, used recv()
//check here for correct connect output from server
recv(sock, buffer, sizeof(buffer), 0);
printf("Output: %s\n", buffer);
if (gSocketSource)
{
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
if (CFRunLoopContainsSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode))
{
CFRunLoopRemoveSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode);
}
CFRelease(gSocketSource);
}
if (socket) //close socket
{
if (CFSocketIsValid(socket))
{
CFSocketInvalidate(socket);
}
CFRelease(socket);
}
}
void ConnectSocket()
{
//socket
CFSocketContext context = {0, NULL, NULL, NULL, NULL};
CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack , (CFSocketCallBack)ConnectCallBack, &context);
//address
struct sockaddr_in socketAddress;
memset(&socketAddress, 0, sizeof(socketAddress));
socketAddress.sin_len = sizeof(socketAddress);
socketAddress.sin_family = AF_INET;
socketAddress.sin_port = htons(5010);
socketAddress.sin_addr.s_addr = inet_addr("10.10.10.253");
gSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, theSocket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), gSocketSource, kCFRunLoopDefaultMode);
CFDataRef socketData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&socketAddress, sizeof(socketAddress));
CFSocketError status = CFSocketConnectToAddress(theSocket, socketData, 30); //30 second timeout
//check status here
CFRelease(socketData);
}
Basically, if the server is unreachable at that port, you will most likely get a kCFSocketTimeout for CFSocketError status. If you are looking to parse a specific response back from the server to determine if the server is ready or not, the ConnectCallBack function will be called upon successful socket connection.
This is just a simple example, make sure not to block the UI by calling socket connections on the main thread such as recv()