im trying to talk between my java app and python client. But it cant seem to connect.
I am not sure if it is because of a wrong IP-adress. Because i read somewhere that you can use the IP of the PC to connect to the virtual device, but i also used the 10.0.x.x address of the virtual device which also doesnt seem to work. In IntelliJ my code does seem to work, only not with the app.
my python client code:
import socket
HOST = "172.20.10.12"
PORT = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
print('connected')
sock.sendall(b'Hello!')
data = sock.recv(1024)
print("1", data, '\n')
sock.sendall(b'Bye\n')
data = sock.recv(1024)
print("2", data, '\n')
print("Socket closed")
sock.close()
And this is the receiving side of my app: StartReceive.java:
package com.example.test;
import java.io.IOException;
class StartReceive implements Runnable {
#Override
public void run() {
try {
Receive.startReceive();
} catch (IOException e) {
e.printStackTrace();
}
}
}
My receive.java:
public class Receive {
static String fromClient;
static String toClient;
public static void startReceive() throws IOException {
ServerSocket server = new ServerSocket(8080);
System.out.println("wait for connection on port 8080");
boolean run = true;
while (run) {
Socket client = server.accept();
System.out.println("got connection on port 8080");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if (fromClient != null) {
toClient = "message is received on server";
System.out.println("send: message is received");
out.println(toClient);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if (fromClient.equals("Bye")) {
toClient = "bye received on server";
System.out.println("send: bye received on server");
out.println(toClient);
client.close();
run = false;
System.out.println("socket closed");
}
}
}
}
}
And then i call it in my mainactivity like this:
To debug the connection issue, first try and set the IP to "localhost" on the client.
You might also usefully print server.getInetAddress() on the server side. It's possible you're not listening on the specific address that your client wanted to connect to.
I would debug this as follows:
Run the server
On the server PC, type the command 'netstat -a -p tcp' (this is Windows, right) and look for something you recognize as the server. The "virtual android device" must show up on the physical PC, since the physical PC is the thing that is physically connected to the physical network.
Try and connect to that server using some utility or other; I prefer telnet. 'telnet '. You should at least see your server's "connected" message on the server console output.
If this all goes well, you now know the server is basically functional.
Once your client is connected, you have a further bug:
You are sending 6 bytes, no newline.
sock.sendall(b'Hello!')
You are expecting to receive data terminated by a newline.
fromClient = in.readLine();
Your receiver is still waiting for the end of the line.
Related
I am trying to connect my Arduino Nano Connect RP2040 with my machine using Python (3.8.8). I want to use WiFi communication protocol and I am currently working on a client-server socket.
Since I am not so familiar with this communication protocol I am following this thread which looks to perform good results. Of course, this thread talks about Ethernet and I am readapting using WiFiNina library which has been developed by Arduino in order to use the module.
Here the code I am running on Arduino:
#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0x08, 0x3A, 0xF2, 0xB1, 0x9D, 0xE0 };
IPAddress ip(192,168,43,98);
// Enter the IP address of the server you're connecting to:
IPAddress server(192,168,0,4);
// Initialize the WiFi client library
// with the IP address and port of the server
WiFiClient client;
char ssid[] = "xxxxx"; // the name of your network
char username[] = "xxxxxxx";
char pass[] = "xxxxxxx";
void setup() {
// start the Wifi connection:
WiFi.beginEnterprise(ssid, username, pass);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 13380)) {
Serial.println("connected");
}
else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
//JSON stuff
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 42;
JsonArray& data = root.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
char json[100];
root.printTo(json);
Serial.print(json);
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// as long as there are bytes in the serial queue,
// read them and send them out the socket if it's open:
if (client.connected()) {
client.print(json);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing:
while(true);
}
}
I have used some functions from WiFiNina (for example .beginEnterprise() in order to connect Arduino to the network).
For what server concerns, here the code in Python:
import socket
import sys
import json
# host = '127.0.0.1'
host = '192.168.0.4'
port = 13380
address = (host, port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(address)
server_socket.listen(5)
# server_socket.connect(address)
print ("waiting for a connection . . .")
conn, address = server_socket.accept()
print ("Connection established: "), address
while True:
output = conn.recv(84048);
if output.strip() == "disconnect":
conn.close()
sys.exit("Disconnect message received - terminate the connection")
conn.send("dack")
elif output:
print(output)
data = json.load(output)
print(data)
I am not interested in sending JSON data, like I have already mentioned I am just readapt the code in thread. I actually need to send data in real-time, but step-by-step :-)
The problem is that I cannot establish the connection between Arduino (client) and Python (server).
From server part, I actually got this error:
Traceback (most recent call last):
File "server_arduino.py", line 18, in <module>
server_socket.bind(address)
OSError: [WinError 10049] The requested address is not valid in its context
For some reasons which I actually did not understand yet, if I would change host in 127.0.0.1 (following suggestions here) the server part starts to work, and it stucks in waiting for a connection . . . printed in my console, because it needs a client to connect.
At this stage, running my Arduino code I got this:
connecting...
connection failed
{"sensor":"gps","time":42,"data":[48.75608,2.302038]}
disconnecting.
So, it does mean to me that I was able to connect to WiFi, but not to server.
Does anyone give me any suggestions?
I know I am really beginner and any suggestions would be really appreciated.
So I am trying to send data from the raspberry pi to unity.
I trying to create socket server to do so.
I can get the socket server running on the raspberry pi and can also look at the port with netstat -tulpn | grep :5005 in the terminal on the machine where the python script is running.
I also tried it on my mac and it also showed up as a TCP-server.
However when I try to connect to the same port and ip via Unity or on another machine it doesn't work. I also can't seem to find the port when listing all of the ports with netstat.
Unity spits out a "Connection refused" error.
Here is the code in Unity in C#
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
public class ClientSocket : MonoBehaviour
{
bool socketReady = false;
TcpClient mySocket;
public NetworkStream theStream;
StreamWriter theWriter;
StreamReader theReader;
public String Host = "192.168.8.137";
public Int32 Port = 5005;
void Start()
{
setupSocket();
TextMessage("SocketTest");
}
public void setupSocket()
{ // Socket setup here
try
{
mySocket = new TcpClient(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
theReader = new StreamReader(theStream);
socketReady = true;
}
catch (Exception e)
{
Debug.Log("Socket error:" + e); // catch any exceptions
}
}
public void TextMessage(string message)
{
if (socketReady == true)
{
theWriter.Write(message);
theWriter.Flush();
}
}
}
here is the code in python, which should be running on the raspberry pi.
import socket
import sys
backlog = 1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.8.137', 5005))
s.listen(1)
try:
print ("is waiting")
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
print (data)
finally:
print("closing socket")
cient.close()
s.close()
I'm new to socket servers, but I really trying to accomplish a connection here.
Thanks for reading!
am pretty sure you need to encode the data that you about to send in c# TcpClient
adding an example from my final project:
string data = "Hello Server!"; //the message in string (important it will be string)
byte[] msg = Encoding.Unicode.GetBytes(data); //encoded the message using unicode (utf-16)
NetworkStream stream = client.GetStream(); //get the tcp client stream
stream.Write(msg, 0, msg.Length); //write the message to the stream
and in the server you suppose to have something like that:
msg = clnt.recv(1024) #reciving the data
msg = msg.decode("utf-16") #decoding the data
print(msg) #printing the data
and i think thats it
and i would recommend using port above 10000 because most of the ports can be used
I'm trying to set up communication through a TCP/IP connection and are having problems with connecting the C# client to the Python Server.
It throws a SocketException:
System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it
I'm pretty sure that it is happening at the line where it tries to connect to the Python server: sender.Connect(remoteEP);
What I've tried
Before I used the IPv4 protocol and Pythons socket.AF_INET but I discovered that it seems like that my parsing of the IP Address in C# makes it an IPv6 address so that's what I'm using now but that didn't resolve the problem.
I also tried using IPAddress.Parse(ip) instead of getting the host first with Dns.GetHostEntry(ip) but that didn't seem to do anything.
The code
The C# code:
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;
public class PyCommunicator : MonoBehaviour {
private string ip = "::1"; // Localhost
private int port = 14654;
public string dataStringToSend
{
get { return dataStringToSend; }
set { dataStringToSend = value; }
}
private void Start()
{
StartCoroutine(RequestServerCoroutine());
}
IEnumerator RequestServerCoroutine()
{
while (true)
{
RequestServer();
yield return new WaitForSecondsRealtime(10);
}
}
public void RequestServer()
{
byte[] bytes = new byte[1024]; // 1 KiloByte
try
{
// Connect to a Remote server,
// and get host IP Address that is used to establish a connection.
// In this case, we get one IP address of localhost that is IPv6 : ::1
// If a host has multiple addresses, you will get a list of addresses
IPHostEntry host = Dns.GetHostEntry(ip);
IPAddress ipAddress = host.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetworkV6,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
// Connect to Remote EndPoint
sender.Connect(remoteEP);
Debug.Log("Successfully established a connection between Unity and Python.");
// Encode the data string into a byte array.
dataStringToSend = "Test from C#";
if (dataStringToSend != "")
{
byte[] msg = Encoding.ASCII.GetBytes(dataStringToSend);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Reset.
dataStringToSend = "";
}
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Debug.LogFormat("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane)
{
Debug.LogFormat("ArgumentNullException: {0}", ane.ToString());
}
catch (SocketException se)
{
Debug.LogFormat("SocketException: {0}", se.ToString());
}
catch (Exception e)
{
Debug.LogFormat("Unexpected exception: {0}", e.ToString());
}
}
catch (Exception e)
{
Debug.LogFormat("Exception from setup: {0}", e.ToString());
}
}
}
The C# code was taken from this link from the client section and modified for my own use.
Python code:
import socket
from time import sleep
class Communicator():
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.data_to_send = None
self.socket = None
self.socket_conn = None
self.socket_addr = None
# Start listening right away.
self.start()
def start(self):
"""Start listening and accept connection."""
self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.socket.bind((self.ip, self.port))
# Begin listening for 1 connection.
self.socket.listen(1)
print("Socket is listening on ip (" + str(self.ip) + ") and port " + str(self.port))
self.socket_conn, self.socket_addr = self.socket.accept()
print("Connection between Unity and Python established. Unity-C# is at: " + str(self.socket_addr))
sleep(5) # TESTING PURPOSES
# Receive.
result = ""
chunk_counter = 0
while True:
# Allow the server to read up to 1024 bytes.
data = self.conn.recv(1024)
chunk_counter += 1
# To minimize lag, read guess in chunks.
if chunk_counter < 5:
result += data.decode()
# If reading the guess is done,
# break out of loop.
if not data:
break
# Send.
self.socket.send("Test from python".encode())
# Close
self.socket.close()
def send_data(self):
"""Send data"""
pass
def receive_data(self):
"""Receive data"""
pass
Communicator('::1', 14654)
It seems like I didn't search the StackOverflow forum enough.
I found a solution in the code and answer given in this StackOverflow answer.
I didn't need to use the actual localhost loopback address and instead needed to get the HOSTNAME address through C#'s DNS function:
Dns.GetHostName()
I also used socket.gethostname() in Python so that they would have same addresses when connecting.
I also changed the whole thing to use IPv4 addresses and found out in the answer of the linked question that the first element in host.AddressList contains IPv6 addresses while the second AND last element contained IPv4 addresses, and that was the missing piece.
UPDATED CODE
C# Code:
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;
public class PyCommunicator : MonoBehaviour {
private int port = 14654;
public string dataStringToSend
{
get { return dataStringToSend; }
set { dataStringToSend = value; }
}
private void Start()
{
StartCoroutine(RequestServerCoroutine());
}
IEnumerator RequestServerCoroutine()
{
while (true)
{
RequestServer();
yield return new WaitForSecondsRealtime(10);
}
}
public void RequestServer()
{
byte[] bytes = new byte[1024]; // 1 KiloByte
try
{
// Connect to a Remote server,
// and get host IP Address that is used to establish a connection.
// In this case, we get one IP address of localhost that is IP : 127.0.0.1
// If a host has multiple addresses, you will get a list of addresses
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = host.AddressList[1];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
// Connect to Remote EndPoint
sender.Connect(remoteEP);
Debug.Log("Successfully established a connection between Unity and Python.");
// Encode the data string into a byte array.
dataStringToSend = "Test from C#";
if (dataStringToSend != "")
{
byte[] msg = Encoding.ASCII.GetBytes(dataStringToSend);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Reset.
dataStringToSend = "";
}
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Debug.LogFormat("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane)
{
Debug.LogFormat("ArgumentNullException: {0}", ane.ToString());
}
catch (SocketException se)
{
Debug.LogFormat("SocketException: {0}", se.ToString());
}
catch (Exception e)
{
Debug.LogFormat("Unexpected exception: {0}", e.ToString());
}
}
catch (Exception e)
{
Debug.LogFormat("Exception from setup: {0}", e.ToString());
}
}
}
Python Code:
import socket
from time import sleep
class Communicator():
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.data_to_send = None
self.socket = None
self.socket_conn = None
self.socket_addr = None
# Start listening right away.
self.start()
def start(self):
"""Start listening and accept connection."""
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((self.ip, self.port))
# Begin listening for 1 connection.
self.socket.listen(1)
print("Socket is listening on ip (" + str(self.ip) + ") and port " + str(self.port))
self.socket_conn, self.socket_addr = self.socket.accept()
print("Connection between Unity and Python established. Unity-C# is at: " + str(self.socket_addr))
sleep(5) # TESTING PURPOSES
# Receive.
result = ""
chunk_counter = 0
while True:
# Allow the server to read up to 1024 bytes.
data = self.conn.recv(1024)
chunk_counter += 1
# To minimize lag, read guess in chunks.
if chunk_counter < 5:
result += data.decode()
# If reading the guess is done,
# break out of loop.
if not data:
break
# Send.
self.socket.send("Test from python".encode())
# Close
self.socket.close()
def send_data(self):
"""Send data"""
pass
def receive_data(self):
"""Receive data"""
pass
Communicator(socket.gethostname(), 14654)
I am trying to establish a connection between an android phone(as server) and my computer(client in python) to send messages from the android phone to PC.
My Problem is that the app keeps crashing and I don't really know how to set the ip's.
So what I do is when the app opens I give it the computers IP and the port at which I need to send the message and then I click "send button".
Down below I have given the code that I have tried but the app crashes at the socket.send(sendPacket);
Android Code
public class MainActivity extends Activity {
private EditText ipInput;
private EditText portInput;
private EditText messageInput;
private Button sendButton;
private DatagramSocket socket;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ipInput = (EditText) findViewById(R.id.address);
portInput = (EditText) findViewById(R.id.port);
messageInput = (EditText) findViewById(R.id.message);
sendButton = (Button) findViewById(R.id.send);
sendButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String message = messageInput.getText().toString();
Log.e("TAG",message);
sendPacket(message);
}
});
}
private void sendPacket(String message) {
byte[] messageData = message.getBytes();
try {
InetAddress addr = InetAddress.getByName(ipInput.getText().toString());
int port = Integer.parseInt(portInput.getText().toString());
DatagramPacket sendPacket = new DatagramPacket(messageData, 0, messageData.length, addr, port);
if (socket != null) {
socket.disconnect();
socket.close();
return;
}
socket = new DatagramSocket(port);
socket.send(sendPacket);
} catch (UnknownHostException e) {
Log.e("MainActivity sendPacket", "getByName failed");
} catch (IOException e) {
Log.e("MainActivity sendPacket", "send failed");
}
}
#Override
public void onDestroy() {
super.onDestroy();
socket.disconnect();
socket.close();
}
}
Python Code:
My python code is also there, I bind the IP at 0.0.0.0 so I can get packet from anyone trying to communicate.
from socket import *
PORT = 7000
IP = "0.0.0.0"
sock = socket(AF_INET, SOCK_DGRAM) # SOCK_DGRAM means UDP socket
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.bind((IP, PORT))
while True:
print "Waiting for data..."
data, addr = sock.recvfrom(1024) # blocking
print "received: " + data
To sum it all up. I really need help with setting ip's, whose ip should I give to the android phone(the phone's or the laptops) and whose ip should I give to the laptop in the python code.
Secondly why does the app crash at "socket.send(sendPacket);" inside the send packet method.
If you need more details let me know in the comments.
So I can't answer you why the app is crashing but I can answer the IP question.
The client (laptop) needs the servers ip (in the same network its 192.168.X.XXX).
The server (phone) might also need his own ip.
The client might also need his own ip.
But notice that the server doesn't need the clients ip, it's open for all connections (except you want to white/black-list certain ip´s).
I did the same things with just some ip differences, works for me.
I have an app on which i press a button and it should turn on/off an led on a raspberry pi.
the code on android studio looks like this :
onPressed: () async {
setState(() {
instruction = power;
power = power == 'on' ? 'off' : 'on';
print('$instruction');
});
int port = 9999;
final socket = await EasyUDPSocket.bindBroadcast(port);
if (socket != null) {
socket.send(ascii.encode('$instruction'), '192.168.0.105', port);
final resp = await socket.receive();
print('Client $port received: $resp');
// `close` method of EasyUDPSocket is awaitable.
await socket.close();
print('Client $port closed');
}
},
the '192.168.0.105' is the ipv4 address of the raspberry pi(this can be found by typing "ipconfig" for windows in cmd and by "ifconfig" in an rpi)
the python code on the rpi or any pc will be
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
print("socket created")
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(("192.168.0.105",9999))
while True:
print("Waiting for data...")
data, addr = s.recvfrom(1024) # blocking
instruction = data.decode("utf-8")
if instruction == 'off':
print('turn off the led')
else:
print("turn on the led")
the python code is a bit customized for the led purpose but i'm sure you'll understand how to work with it!
I have a UDP socket application where I am working on the server side. To test the server side I put together a simple python client program that sends the message "hello world how are you". The server, should then receive the message, convert to uppercase and send back to the client. The problem lies here: I can observe while debugging that the server is receiving the message, applies the conversion, sends the response back and eventually waits for another message. However the python client is not receiving the message but wait's endlessly for the response from the server.
I found (an option) through the web that in order for the client to receive a response back it needs to bind to the server, which goes against what I have seen in a text book (The Linux Programming Interface). Nevertheless, I tried to bind the client to the server and the python program failed to connect at the binding line (don't know if I did it correctly). Python version is 2.7.5. The client program runs on RedHat and the server runs on a target module with Angstrom (it's cross compiled for a 32 bit processor).
Here is the code for the client:
import socket
import os
UDP_IP = "192.168.10.4"
UDP_PORT = 50005
#dir_path = os.path.dirname(os.path.realpath(__file__))
MESSAGE = "hello world how are you"
print "UDP target IP: ", UDP_IP
print "UDP target port: ", UDP_PORT
print "message: ", MESSAGE
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#sock.bind((UDP_IP, UDP_PORT))
print "Sending message..."
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
print "Message sent!"
print "Waiting for response..."
data = sock.recv(1024)
print "Received", repr(data)
And here is the code for the server:
void server_side(void)
{
printf("Server start up.\n");
struct sockaddr_in svaddr;
struct sockaddr_in claddr;
int sfd;
int j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
char claddrStr[INET_ADDRSTRLEN];
//int output = open("test_output.txt", O_WRONLY|O_CREAT, 0664);
printf("Creating new UDP socket...\n");
sfd = socket(AF_INET, SOCK_DGRAM, 0); /* Create Server Socket*/
if (sfd == -1)
{
errExit("socket");
}
printf("Socket has been created!\n");
memset(&svaddr, 0, sizeof(struct sockaddr_in));
svaddr.sin_family = AF_INET;
svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
svaddr.sin_port = htons(PORT_NUM);
printf("Binding in process...\n");
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_in))
== -1)
{
errExit("bind");
}
printf("Binded!\n");
/* Receive messages, convert to upper case, and return to client.*/
for(;;)
{
len = sizeof(struct sockaddr_in);
numBytes = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &claddr, &len);
if (numBytes == -1)
{
errExit("recvfrom");
}
if (inet_ntop(AF_INET, &claddr.sin_addr, claddrStr,
INET_ADDRSTRLEN) == NULL)
{
printf("Couldn't convert client address to string.\n");
}
else
{
printf("Server received %ld bytes from (%s, %u).\n", (long)
numBytes,
claddrStr, ntohs(claddr.sin_port));
}
claddr.sin_port = htons(PORT_NUM);
for (j = 0; j< numBytes; j++)
{
buf[j] = toupper((unsigned char) buf[j]);
}
if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len)
!= numBytes)
{
fatal("sendto");
}
}
}
Again the problem is I am not receiving the response and printing the message back on the client terminal. I should receive the same message in all uppercase letters. I feel like I am missing a small detail. Thanks for the help!
Quick and dirty:
Remove this line from your C code:
claddr.sin_port = htons(PORT_NUM);
Now why:
When you send a message in your python script, your operating system will fill a UDP packet with the destination IP address and port you specified, the IP address of the machine you are using on the source IP field, and finally, a source port assigned "randomly" by the OS. Do notice, this is not the same port as the destination port, and even if it was the case, how would you know what program will receive the source message?(both would be hearing messages from the same port) Luckily, this is not possible.
Now, when your C code receives this packet, it will know who sent the message, and you have access to this information though the sockaddr struct filled by recvfrom. If you want to send some information back, you must send the packet with a destination port(as seen by the server) equal to the source port as seen by the client, which again, is not the same port that you are listening on the server. By doing claddr.sin_port = htons(PORT_NUM), you set overwrite the field that contained the source port of the client with the server port, and when you try to send this packet, 2 things may happen:
If the client ran from the same computer, the destination IP and
source IP will be the same, and you've just set the destination port
to be the port that the server is listening, so you will have a
message loop.
If running on different computers, the packet will be
received by the client computer, but there probably won't be any
programs waiting for messages on that port, so it is discarded.
A half-baked analogy: you receive a letter from a friend, but when writing back to him, you change the number of his house with the number of your house... does not make much sense. Only difference is that this friend of yours moves a lot, and each letter may have a different number, but that is not important.
In theory, you must bind if you want to receive data back, in this case bind is an equivalent to listening to that port. This answer clarifies why it was not necessary in this case: https://stackoverflow.com/a/14243544/6253527
If you are on linux, you can see which port you OS assigned for your UDP socket using sudo ss -antup | grep python
N. Dijkhoffz, Would love to hear how you fixed it and perhaps post the correct code.