WINSOCK , TCP : No connection between two computers - c

I'm not able to connect to a TCP server on a computer from a client in another computer on the same local network. I'm Getting an error 10060.
I'm able to connect to the server if the client is launched on the same computer as the server.
Here's some info about the server, then the client
(client running on .30 , server = .50)
TCP info of client
Here we can see that my client is sending a SYN signal to the correct IP/PORT
TCP info of Server
The server seems to be listening to any IP and port. So it sounds like I'm not understanding how to set up setsockopt.
Here's the main() of the server that doesnt work if the client isn't on the same computer:
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
// Start of experiment
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
{
printf("The Winsock 2.2 dll was found okay\n");
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
//int option = 1;
bool option = TRUE;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
//signal(SIGPIPE, SIG_IGN); Sigpipe doesnt exist in NT. I need to implement something ...
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof(option)) < 0){
perror("ERROR: setsockopt failed\n");
printf("Error : %i\n",WSAGetLastError());
printf("port was: %i\n",port);
printf("Ip Was : %lu\n",serv_addr.sin_addr.s_addr);
WSACleanup();
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
WSACleanup();
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
WSACleanup();
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count + 1) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
close(connfd);
continue;
}
/* Client settings */
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
WSACleanup();
return EXIT_SUCCESS;
}
I somehow managed to make it work when messing around parameters, but I'm not able to reproduce it since I don't understand how winsock works yet.
I tried to disable Firewall on both computers, but it didn't help.
Thanks a lot for your help !

Related

Worker thread exits some time later

Here is a simple echo program using sockets and multi threads, it compiles and runs well in my Ubuntu if the client(via telnet) and server run on the same machine, but when I remotely connect to the server via telnet from another machine, it initially runs well(echos my message back every time), but some time later, there is no echo anymore even the telnet session is still alive, i am not sure where the problem is, can someone give some hits on this? I am new to multi thread programming and socket programming, learning on that.
#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024
void* worker(void* sockId)
{
int socketId = *(int*)sockId;
int data_len = 1;
char data[MAX_DATA];
while(data_len > 0)
{
data_len = recv(socketId, data, MAX_DATA, 0);
if (data_len > 0)
{
send(socketId, data, data_len, 0);
data[data_len] = '\0';
printf("Sent message: %s", data);
}
}
printf("Client disconnected\n");
close(socketId);
}
int main(int argc, char* argv[])
{
if (argc <= 1)
{
printf("missing argument: port\n");
exit(-1);
}
struct sockaddr_in server;
struct sockaddr_in client;
int sock;
int new_connection;
int sockaddr_len = sizeof(struct sockaddr_in);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
{
perror("server socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
server.sin_addr.s_addr = INADDR_ANY;
bzero(&server.sin_zero, 8);
if ((bind(sock, (struct sockaddr*)&server, sockaddr_len)) == ERROR)
{
perror("bind: ");
exit(-1);
}
if ((listen(sock, MAX_CLIENTS)) == ERROR)
{
perror("listen: ");
exit(-1);
}
while(1)
{
if ((new_connection = accept(sock, (struct sockaddr*)&client, &sockaddr_len)) == ERROR)
{
perror("accpet: ");
exit(-1);
}
printf("New Client connected from port: %d and IP: %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
pthread_t thread;
pthread_create(&thread, NULL, worker, (void*)&new_connection);
pthread_detach(thread);
}
close(sock);
pthread_exit(NULL);
return 0;
}
Add some logging and you'll probably find that your code is blocked in send. You use naive, sequential I/O, so if the other end of the connection stops reading data, soon you do too.

accept() returning invalid argument

Learning about TCP connections. Can anyone see why my accept() call is erroring with an "invalid argument"? I can't see what I am doing wrong. Thanks!
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size;
fd_set read_set;
struct timeval tv;
// initialize the fd set
FD_ZERO(&read_set);
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(6001); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
addr_size = sizeof(clientAddr);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
} else {
fprintf(stdout, "Socket established for client 0\n");
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
} else {
fprintf (stdout, "Binding successful for client 0\n");
}
// ERROR HAPPENS ON THE NEXT LINE
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
} else {
fprintf(stdout, "\tSuccessfully accepted inbound connection from client 0\n");
}
return 0;
}
A call to listen is missing after bind before accept.
I would initialize addr_size to sizeof(clientAddr) and clear clientAddr

Subsequent Messages not Received

I'm working on a networking project. I can successfully send a single message from my client program over to my server program. However, when I send a second message, the server apparently isn't receiving it. I say this because the client program generates output to suggest that the message was sent, but the server shows no reaction at all.
I'm thinking that I am doing something wrong with either select() or FD_ISSET(). Can anyone see what I am doing wrong? Thanks.
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size = sizeof clientAddr;
fd_set read_set;
struct timeval tv;
char buffer[BUFFSIZE];
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(SERVER_PORT); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
// create a listening connection to listen for requests from clients
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
}
if (listen(sockfd, 10) < 0) {
fprintf (stdout, "Listen() failed\n");
perror("listen() failed");
exit (1);
}
// accept the connection
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
}
// initialize the fd set
FD_ZERO(&read_set);
FD_SET(newfd, &read_set); // adding our socket to the set
tv.tv_sec = 0;
tv.tv_usec = TIMEOUT * 1000;
while (1) {
if ( select(newfd+1, &read_set, NULL, NULL, &tv) == -1) {
perror("select failure");
fprintf(stdout, "errno: %d\n", errno);
exit(EXIT_FAILURE);
}
if (FD_ISSET(newfd, &read_set)) {
bzero(buffer, BUFFSIZE);
recv(newfd, &buffer, BUFFSIZE, 0);
fprintf(stdout, "Received message: %s\n", buffer);
}
}
return 0;
}
After each select you need call FD_ZERO(&read_set); FD_SET(newfd, &read_set); again.
So just move those functions into the loop, before select.

C - Server broadcasts IP for client

I need my server to broadcast a message (not that it matters but it contains its IP/port info). What I have currently is the working server broadcast, code below. I'm not sure about setting up the client because usually I would use the IP/port of the server which the client doesn't have until it receives the broadcast. The client never receives anything. Can someone tell me what is wrong.
Server:
struct sockaddr_in server, bcast;
int sockfd;
int blen = sizeof(bcast);
int svrlen = sizeof(server);
char buf[BUFLEN];
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
int broadcastPermission = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&broadcastPermission,sizeof(broadcastPermission)) < 0){
printf("Error setting socket options.");
}
memset(&bcast, 0, sizeof(bcast));
bcast.sin_family = AF_INET;
bcast.sin_port = htons(PORT);
bcast.sin_addr.s_addr = htonl(INADDR_ANY);
string bcastIP = BCASTIP;
if(inet_aton("255.255.255.255", &bcast.sin_addr) == 0){
printf("Broadcast Address error.");
exit(1);
}
if (bind(sockfd, (struct sockaddr*)&server, sizeof(server)) == -1){
printf("Port error.\n");
exit(1);
}
fflush(stdout);
if(int bytes = sendto(sockfd, ipinfo, sizeof(ipinfo), 0, (struct sockaddr*)&bcast, blen) == -1){
printf("Broadcast send error.");
}
else{
printf("Sent"):
}
Client:
struct sockaddr_in server;
int sockfd;
int bytes;
int svrlen = sizeof(server);
char buf[BUFLEN]
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(BPORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
printf("Waiting for broadcast...\n\n");
fflush(stdout);
memset(buf,0,BUFLEN);
bytes = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&server, (socklen_t*)&svrlen);
printf("Received");
}
Your client is not calling bind() on the socket before trying to receive data.
http://cs.baylor.edu/~donahoo/practical/CSockets/code/BroadcastReceiver.c shows the following example which you may find helpful:
void DieWithError(char *errorMessage); /* External error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in broadcastAddr; /* Broadcast Address */
unsigned short broadcastPort; /* Port */
char recvString[MAXRECVSTRING+1]; /* Buffer for received string */
int recvStringLen; /* Length of received string */
if (argc != 2) /* Test for correct number of arguments */
{
fprintf(stderr,"Usage: %s <Broadcast Port>\n", argv[0]);
exit(1);
}
broadcastPort = atoi(argv[1]); /* First arg: broadcast port */
/* Create a best-effort datagram socket using UDP */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct bind structure */
memset(&broadcastAddr, 0, sizeof(broadcastAddr)); /* Zero out structure */
broadcastAddr.sin_family = AF_INET; /* Internet address family */
broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
broadcastAddr.sin_port = htons(broadcastPort); /* Broadcast port */
/* Bind to the broadcast port */
if (bind(sock, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr)) < 0)
DieWithError("bind() failed");
/* Receive a single datagram from the server */
if ((recvStringLen = recvfrom(sock, recvString, MAXRECVSTRING, 0, NULL, 0)) < 0)
DieWithError("recvfrom() failed");
recvString[recvStringLen] = '\0';
printf("Received: %s\n", recvString); /* Print the received string */
close(sock);
exit(0);
}
I need my server to broadcast a message (not that it matters but it contains its IP/port info).
That sounds a lot like service discovery. You should really use the standard mDNS/Zeroconf protocol for that. You can use the Avahi library for that (or use the Avahi service on Linux or Zeroconf on MacOS X).

Unable to connect 2 machines using ipv6 (TCP server client )

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.

Resources