This question is similar to others but I found so much information I am not sure what is important and what not anymore.
What I am doing is a simple chat program where I create the server and my friend and I both have one socket to send messages through.
Server side:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdbool.h>
SOCKET start_server(void)
{
INT iResult;
SOCKET sock;
struct addrinfo *result = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo("192.168.70.3", "666", &hints, &result);
if(iResult)
{
printf("> error: getaddrinfo failed (error code: %d)\n", iResult);
return INVALID_SOCKET;
}
// Create a SOCKET for connecting to server
sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if(sock == INVALID_SOCKET)
{
printf("> error: socket failed (error code: %d)\n", WSAGetLastError());
freeaddrinfo(result);
return INVALID_SOCKET;
}
// Setup the TCP listening socket
iResult = bind(sock, result->ai_addr, (int) result->ai_addrlen);
if(iResult == SOCKET_ERROR)
{
printf("> error: bind failed (error code: %d)\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(sock);
return INVALID_SOCKET;
}
freeaddrinfo(result);
return sock;
}
int main(int argc, char **argv)
{
char buf[1024];
SOCKET serverSock;
SOCKET socks[2];
WSADATA wsaData;
INT iRetval;
if((iRetval = WSAStartup(MAKEWORD(2, 2), &wsaData)))
{
printf("> error: Startup failed(error code: 0xF0%x)\n", iRetval);
return 0xFF;
}
printf("> Connecting to server...\n");
serverSock = start_server();
printf("> Connected to server...\n");
printf("> Listening for connections..\n");
listen(serverSock, 0);
socks[0] = accept(serverSock, NULL, NULL);
printf("> One client connected\n");
listen(serverSock, 0);
socks[1] = accept(serverSock, NULL, NULL);
printf("> Another client connected\n");
while(1)
{
if(recv(socks[0], buf, sizeof(buf), 0) > 0)
{
send(socks[1], buf, strlen(buf) + 1, 0);
}
if(recv(socks[1], buf, sizeof(buf), 0) > 0)
{
send(socks[0], buf, strlen(buf) + 1, 0);
}
Sleep(10);
}
return 0;
}
Client side:
SOCKET user_connect(void)
{
SOCKET sock = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("public_ip_address", "666", &hints, &result);
if(iResult)
{
printf("> error: getaddrinfo failed (error code: %d)\n", iResult);
return INVALID_SOCKET;
}
// Attempt to connect to an address until one succeeds
for(ptr = result; ptr; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if(sock == INVALID_SOCKET)
{
printf("> error: socket failed (error code: %d)\n", WSAGetLastError());
return INVALID_SOCKET;
}
// Connect to server.
printf("> Trying to connect to: cannon name[%s], family[%d], protocol[%d], socket type[%d], flags[%d]\n", ptr->ai_canonname, ptr->ai_family, ptr->ai_protocol, ptr->ai_socktype, ptr->ai_flags);
iResult = connect(sock, ptr->ai_addr, (int) ptr->ai_addrlen);
if(iResult == SOCKET_ERROR)
{
closesocket(sock);
sock = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
return sock;
}
The problem is that it fails establishing a connection. Note that it works when I use a local ip address instead of public_ip_address and open each component on my PC only.
So I got my public IP, local IP, even set up a Port Forwarding but I am not sure what gives.
My question is what I am doing wrong and what I need to do to establish a connection.
Related
I've been working on a connect 4 game that contains both the client and server code in my main function for a TCP connection.I'm unable to connect over the internet. I've tried running my client code on a laptop that isn't on my LAN specifying my LAN's public IP and the desired port number. However,keep getting a connection refused as my perror message when connect fails.
//client code
if(argc == 3){
turn = CLIENT;
int status, client_sockfd;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if((status = getaddrinfo(argv[1], argv[2], &hints, &res)) != 0){
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
if((client_sockfd = socket(res -> ai_family, res -> ai_socktype, res -> ai_protocol)) == -1){
fprintf(stderr, "socket creation error: %s\n", gai_strerror(client_sockfd));
exit(1);
}
if((connect(client_sockfd, res -> ai_addr, res -> ai_addrlen)) == -1){
perror("cannot connect");
exit(1);
}
freeaddrinfo(res); //free res structure
//Start of Game: Client
recv(client_sockfd, player1, 25, 0);
printf("Player 2, enter your name:\n");
fgets(player2, sizeof(player2), stdin);
send(client_sockfd, player2, 25, 0);
sock = client_sockfd;
}
//server network code
else{
turn = SERVER;
int server_sockfd;
printf("Setting up the game\n");
//server port
if(argc == 2)
myport = argv[1];
else
myport = "12345";
int status, sock_fd;
int opt = 1;
struct addrinfo hints, *res;
struct sockaddr_storage their_addr;
socklen_t addr_size;
memset(&hints, 0, sizeof(hints)); //make sure hints is empty
hints.ai_family = AF_UNSPEC; //ipv6 or ipv4 doesn't matter
hints.ai_socktype = SOCK_STREAM; //require TCP stream sockets
hints.ai_flags = AI_PASSIVE;
//load res adderinfo struct
if((status = getaddrinfo(NULL, myport, &hints, &res)) != 0){
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
//create socket with res
if((sock_fd = socket(res -> ai_family, res -> ai_socktype, res -> ai_protocol)) == -1){
fprintf(stderr, "socket creation error: %s\n", gai_strerror(sock_fd));
exit(1);
}
//reuseable socket
if(setsockopt(sock_fd,SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1){
perror("setsockopt");
exit(1);
}
//bind socket for use
if((bind(sock_fd, res -> ai_addr, res-> ai_addrlen)) == -1){
perror("binding fail");
exit(1);
}
//listen with a backlog of 5
listen(sock_fd, 5);
addr_size = sizeof(their_addr);
if((server_sockfd = accept(sock_fd, (struct sockaddr *)&their_addr, &addr_size)) == -1){
perror("accepting failure");
exit(1);
}
freeaddrinfo(res); //free res structure
//Start of Game: Server
printf("Player 1, please enter your name:\n");
fgets(player1, sizeof(player1), stdin);
send(server_sockfd, player1, 25, 0);
recv(server_sockfd, player2, 25, 0);
sock = server_sockfd;
}
Any thoughts? From my understanding, as the client, my packet should reach the server's gateway and NAT should use my destination port to redirect my messages to the server?
I've got a small program with a client and server. The server starts, connects to the client and receives a host and second port number from the client, then sends some information back to the client about it's directory. The function in the server that sends data back works something like this:
void sendStuff(char *host, char *port) {
int sockfd, numbytes;
struct addrinfo hints, *servinfo;
struct sockaddr_storage client_info;
socklen_t addr_size;
size_t i = 0;
int rv;
// clear hints
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
memset(&servinfo, 0, sizeof(servinfo));
if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
}
// create socket
sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sockfd == -1) {
perror("There was an error creating your socket.");
close(sockfd);
exit(1);
}
// connect using socket
int conn;
conn = connect(sockfd, servinfo->ai_addr, servinfo->ai_addrlen);
if(conn == -1) {
perror("Error connecting to server.");
close(sockfd);
exit(1);
}
send(sockfd, "hey!", strlen("hey!"), 0);
}
Currently testing over localhost, which is being printed as 16.2.197.67 on the client. That doesn't seem like a localhost IP, so I suppose I could be screwing up the host somehow. Connecting to the waiting socket over telnet works, but not through this function.
All is doing fine here, except that the client can't receive the message, or the server can't send it, I don't know.
I have really little time, so I can't waste it anymore trying to handle this problem, so I turn to you guys. Just one thing that I think (maybe) you have to know: the server is under my network, the client is under my school network.
P.S. the different IPs for the server is because I'm behind a NAT, no problem with that.
Client code
const char* IPSERVER = "87.21.70.136";
int main(int argc, char *argv[]){
struct addrinfo hints, *serverInfo;
int s;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo(IPSERVER, "50", &hints, &serverInfo) != 0){
printf("Errore getaddrinfo(). Chiusura...\n");
exit(-1);
}
s = socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
printf("Porta: %d\n", ((struct sockaddr_in * ) serverInfo->ai_addr)->sin_port);
if(connect(s, serverInfo->ai_addr, serverInfo->ai_addrlen) < 0)
perror("Errore connect()");
char buf[2000];
int bytes_rec;
if((bytes_rec = recv(s, buf, sizeof buf, 0)) < 0)
perror("Errore recv");
printf("%s\n",buf);
close(s);
return 0;
}
Server code
struct sockaddr_storage clientAddr;
socklen_t addrSize;
struct addrinfo hints, *myInfo;
int s, newS;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo("192.168.1.2", "50", &hints, &myInfo) < 0)
perror("Errore getaddrinfo()");
printf("Porta: %d\n", ((struct sockaddr_in *) myInfo->ai_addr) -> sin_port);
s = socket(myInfo->ai_family, myInfo->ai_socktype, myInfo->ai_protocol);
if(s < 0)
perror("Errore socket()");
printf("Socket stabilita.\n");
if(bind(s, myInfo->ai_addr, myInfo->ai_addrlen) < 0)
perror("Errore bind()");
printf("Porta creata.\n");
if(listen(s, 5) < 0)
perror("Errore listen()");
printf("Server in ascolto...\n");
addrSize = sizeof clientAddr;
if((newS = accept(s, (struct sockaddr * )&clientAddr, &addrSize) < 0))
perror("Errore accept()");
printf("Invio messaggio in corso...\n");
char *msg = "ciao, mi vedi?";
int len, bytes_sent;
len = strlen(msg);
if((bytes_sent = send(newS, msg, len, 0)) < 0)
perror("Errore send()");
printf("Messaggio inviato.\n");
closesocket(newS);
closesocket(s);
WSACleanup();
return 0;
}
Client output
Porta: 12800
Errore recv: Connection reset by peer
Server output
Porta: 12800
Socket stabilita.
Porta creata.
Server in ascolto...
Invio messaggio in corso...
Errore send(): No error
Messaggio inviato.
Process returned 0 (0x0) execution time : 4.789 s
Press any key to continue.
The server code is clearly using the WinSock API, which means the server is running on Windows.
Socket handles on Windows are unsigned values, so int is the wrong data type to use for them. You need to use the SOCKET type instead. And compare the return value of socket() and accept() again the INVALID_SOCKET constant.
Ignoring socket creation errors and passing invalid sockets to send() and recv() can cause them to fail.
perror() operates on errno, which WinSock (and the Win32 API in general) does not use. That would explain the "no error" message after send() fails, because errno is 0. You have to use WSAGetLastError() instead to get a WinSock error code when a WinSock function fails.
With that said, try this server code:
void psocketerror(const char *msg, int err)
{
fprintf(stderr, "%s: %d\n", msg, err);
}
void psocketerror(const char *msg)
{
psocketerror(msg, WSAgetLastError());
}
int main(int argc, char *argv[])
{
struct sockaddr_storage clientAddr;
socklen_t addrSize;
struct addrinfo hints, *myInfo;
SOCKET s, newS;
int err;
WSADATA wsa;
err = WSAStartup(MAKEWORD(2, 0), &wsa);
if (err != 0) {
psocketerror("Errore WSAStartup()", err);
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo("192.168.1.2", "50", &hints, &myInfo)) < 0) {
psocketerror("Errore getaddrinfo()", err);
WSACleanup();
return 1;
}
printf("Porta: %d\n", ntohs(((struct sockaddr_in *)(myInfo->ai_addr))->sin_port));
s = socket(myInfo->ai_family, myInfo->ai_socktype, myInfo->ai_protocol);
if (s == INVALID_SOCKET) {
psocketerror("Errore socket()");
WSACleanup();
return 1;
}
printf("Socket stabilita.\n");
if (bind(s, myInfo->ai_addr, myInfo->ai_addrlen) < 0) {
psocketerror("Errore bind()");
closesocket(s);
WSACleanup();
return 1;
}
printf("Porta creata.\n");
if (listen(s, 5) < 0) {
psocketerror("Errore listen()");
closesocket(s);
WSACleanup();
return 1;
}
printf("Server in ascolto...\n");
addrSize = sizeof clientAddr;
newS = accept(s, (struct sockaddr * )&clientAddr, &addrSize)
if (newS === INVALID_SOCKET) {
psocketerror("Errore accept()");
closesocket(s);
WSACleanup();
return 1;
}
printf("Invio messaggio in corso...\n");
char *msg = "ciao, mi vedi?";
int len, bytes_sent;
len = strlen(msg);
if ((bytes_sent = send(newS, msg, len, 0)) < 0) {
psocketerror("Errore send()");
closesocket(newS);
closesocket(s);
WSACleanup();
return 1;
}
printf("Messaggio inviato.\n");
closesocket(newS);
closesocket(s);
WSACleanup();
return 0;
}
Hi I'm new to socket programming. I'm currently writing c code for client, which is my computer, to send something to local host 127.0.0.1 and see if local host has got the request and anything back. I can already get connected to the local host but I don't know what command do I use to test if I can talk to the local host.
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib, "ws2_32.lib") //Winsock Library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
char *message , server_reply[2000];
int recv_size;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d\n", WSAGetLastError());
return 1;
}
printf("Socket created.\n");
//server.sin_addr.s_addr = 127.0.0.1;
//server.sin_addr.s_addr = inet_addr("74.125.224.72"); //google IP address
server.sin_addr.s_addr = inet_addr("127.0.0.1"); //local host IP
server.sin_family = AF_INET;
//server.sin_port = htons(80);//IIS port
server.sin_port = htons(60441); //local port
//server.sin_port = 80;
//Connect to remote server
if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("connect error:%d\n", WSAGetLastError());
closesocket(s);
WSACleanup();
system("pause");
return 1;
}
puts("Connected\n");
closesocket(s);
WSACleanup();
system("pause");
return 0;
}
Once you get a connection, you can use send to send a message to the remote server and recv to get a response back. Exactly what you send and what you expect to receive depend entirely on what service you're talking to.
EDIT:
As an example, suppose you're talking to a web server and you want to retrieve the main page. You could do this:
char request[] = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";
size_t bytesSent = send(s, request, strlen(request), 0);
if (bytesSent == -1) {
printf("Error sending: %d\n", WSAGetLastError());
return 1;
}
char response[10000];
memset(response, 0, sizeof(response));
size_t bytesRead = recv(s, response, sizeof(response), 0);
if (bytesRead == -1) {
printf("Error receiving: %d\n", WSAGetLastError());
return 1;
}
printf("response from web server: %.*s\n", bytesRead, response);
I was trying to do a simple tcp server client using ipv6. It works on the same machine for ipv6 and ipv4 but when on different machines ipv6 fails to connect.
Server Code
int main(int argc, char* argv[])
{
int sockfd,new_fd,rv,yes=1;
struct addrinfo hints,*servinfo,*p;
struct sockaddr_storage their_addr;
socklen_t addr_size;
SOCKET listenSocket,clientSocket;
WSADATA w;
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
//ip=argv[1];
//port=argv[2];
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET6;
hints.ai_socktype=SOCK_STREAM;
hints.ai_flags=AI_NUMERICHOST;
if((rv = getaddrinfo("fe80::c0a8:0160","5002",&hints,&servinfo)) != 0)
{
perror("\nGetaddrinfo failed\n");
return 1;
}
//Creating socket
listenSocket = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);
if(listenSocket == INVALID_SOCKET)
{
printf("\nSocket failed with error \n");
WSACleanup();
}
//setting non blocking mode
u_long iMode = 1;
rv = ioctlsocket(listenSocket,FIONBIO,&iMode);
if(rv == SOCKET_ERROR)
{
printf("\nioctl failed\n");
WSACleanup();
}
rv = bind(listenSocket,servinfo->ai_addr,(int)servinfo->ai_addrlen);
if(rv == SOCKET_ERROR)
{
perror("\nBind: \n");
}
freeaddrinfo(servinfo);
rv = listen(listenSocket,SOMAXCONN);
if(rv == SOCKET_ERROR)
{
perror("listen");
return 1;
}
// now accept an incoming connection:
char recvbuf[DEFAULT_BUFLEN];
int buflen = DEFAULT_BUFLEN;
SOCKET AcceptSocket;
while (1)
{
AcceptSocket = SOCKET_ERROR;
while (AcceptSocket == SOCKET_ERROR)
{
AcceptSocket = accept(listenSocket, NULL, NULL);
}
printf("Server: Client Connected!\n");
listenSocket = AcceptSocket;
rv = recv(listenSocket,recvbuf,buflen,0);
break;
}
printf("Received %d bytes from client \n",rv);
closesocket(listenSocket);
closesocket(AcceptSocket);
return 0;
}
Client Code
int main(int argc,char* argv[])
{
struct addrinfo hints,*servinfo,*p;
int rv;
SOCKET connectSocket;
WSADATA w;
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
//resetting memory
memset(&hints,0,sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICHOST;
//getting values
if((rv = getaddrinfo("fe80::c0a8:160","5002",&hints,&servinfo)) != 0)
{
perror("Getaddrinfo failed");
return 1;
}
//Creating socket
connectSocket = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);
if(connectSocket == INVALID_SOCKET)
{
perror("Socket create : ");
}
rv = connect(connectSocket,servinfo->ai_addr,(int)servinfo->ai_addrlen);
if(rv == SOCKET_ERROR)
{
perror("Socket Connect : ");
}
//free memory
freeaddrinfo(servinfo);
// Send and receive data.
int bytesSent;
char sendbuf[200] = "Client: Sending some test string to server...";
char recvbuf[200] = "";
bytesSent = send(connectSocket, sendbuf, strlen(sendbuf), 0);
printf("Client: send() - Bytes Sent: %ld\n", bytesSent);
closesocket(connectSocket);
return 0;
}
The aim is just to print how many bytes transferred.
It appears that you're using a link local address. Are you sure for that? Also, I'd suggest you check your firewall settings first.
EDIT:
Try to include the zone ID. When you issue the ipconfig in command prompt, you should be able to get addresses like fe80::c0a8:0160%21 where %21 is the zone ID. It's important when you use link local addresses according to this answer.