The following works without error on OSX 10.6, but fails in the iphone simulator using SDK 4.1
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <string.h>
int main(void) {
int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
struct sockaddr_un sock_addr;
memset(&sock_addr, 0, sizeof(struct sockaddr_un));
sock_addr.sun_family = AF_UNIX;
strcpy(sock_addr.sun_path, "/tmp/sock");
int err = bind(sock, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr_un));
if(err == -1) {
perror("bind: ");
}
}
Error is "Address family not supported by protocol family"
Any ideas?
You really need to check sock already - most likely, the socket creation is what failed already.
My guess is that AF_UNIX/SOCK_DGRAM is not supported; try SOCK_STREAM instead.
Related
Until recently, the following code worked perfectly in my project. But since a few days ago, it no longer works. I can replace the NSLog statements with printf statements, replace the other Obj-C style statements and compile with g++ in terminal it works just fine.
It should just connect to a very primitive server on a Raspberry Pi, send a single character 'R', and read back a 2-Byte integer. When I compiled or ran it in XCode months ago it worked. When I compile now in terminal with g++ it works. When I run in XCode now, though, it fails to open the socket and reports setDAC: connection failed.
I fear I may be going insane. Did Apple hide some new setting I need to turn on network access in XCode 9.4.1? Any advice?
Previously functional code in XCode:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include "stdio.h"
.
.
.
float readDAC(uint8_t ch){
if(!isConnected){
const char *servIP = [[txtIPAddress stringValue] UTF8String];
in_port_t servPort = 5001;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0){
NSLog(#"setDAC: Socket creation failed\n");
ok = false;
}
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
int rtnVal = inet_pton(AF_INET, servIP, &servAddr.sin_addr.s_addr);
if(ok){
if(rtnVal == 0){
NSLog(#"setDAC: inet_pton() failed: invalid address string\n");
ok = false;
}
else if (rtnVal < 0){
NSLog(#"setDAC: inet_pton() failed\n");
ok = false;
}
servAddr.sin_port = htons(servPort);
}
if(ok) if(connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
NSLog(#"setDAC: connection failed\n");
ok = false;
}
datastream = fdopen(sock, "r+");
isConnected = true;
}
//send 'R' to read
//send 'W' to write
char writeChar = 'R';
if([AD5754 intValue]==1){
uint8_t writeChannel;
int16_t setVal;
float theVal;
uint8_t nDAC = 0;
if(ch>3) nDAC = 1;
ch = ch%4;
ch = 16*nDAC+ch;
writeChannel = ch;
fwrite(&writeChar, sizeof(writeChar), 1, datastream);
fwrite(&writeChannel, sizeof(writeChannel), 1, datastream);
fread(&setVal, sizeof(setVal), 1, datastream);
int16_t theSetVal;
theSetVal = ntohs(setVal);
theVal = (float)theSetVal/100;
NSLog(#"Read channel %i: %0.2f", ch, theVal);
fflush(datastream);
fclose(datastream);
return theVal;
}
I paid Apple the $99 annual fee to join the developer program and now the network coding works again. Not impressed with Apple, but ok.
I wouldn't mind paying to recover the functionality if it was documented or some notice was given. But I struggled for a few days before getting desperate enough to try throwing money at the problem, randomly.
i'm trying to create server with TCP IP protocol
But it doesn't accept connection, or may be because of listen
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd,newsockfd,num_port,serveur_T;
socklen_t client_T;
char buffer[200];
struct sockaddr_in adr_serveur, adr_client;
int n;
if (argc < 2)
{
fprintf(stderr, "nombre d'arguments est insuffisant\n");
exit(1);
}
sockfd=socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
error("erreur de creation de socket");
}
serveur_T=sizeof(adr_serveur);
bzero((char*)&adr_serveur, serveur_T);
num_port=atoi(argv[1]);
adr_serveur.sin_family=AF_INET;
adr_serveur.sin_addr.s_addr=INADDR_ANY;
adr_serveur.sin_port=htons(num_port);
serveur_T=sizeof(adr_serveur);
if (bind ( sockfd,(struct sockaddr *) &adr_serveur,serveur_T)<0)
{
error(" Erreur de binding");
}
listen (sockfd,5);
client_T= sizeof(adr_client);
newsockfd= accept(sockfd,(struct sockaddr *) &adr_client,&client_T);
if ( newsockfd<0)
{
error("Erreur socket accept");
}
bzero(buffer, 200);
return 0;}
When I execute server I got this error
Erreur socket accept: Operation not supported
Second question: Can I use an IRC client and connect it to my server ? In my school we have Linux servers so I'm wondering if I can use them as a hostname ?
Thanks
i'm trying to create server with TCP IP protocol
You have created a SOCK_DGRAM (UDP) socket, not a SOCK_STREAM (TCP) socket. You cannot call listen() or accept() on a UDP socket, only on a TCP socket. listen() is reporting an EOPNOTSUPP error:
listen(2)
EOPNOTSUPP
The socket is not of a type that supports the listen() operation.
You are ignoring that error, and then accept() is reporting the same error:
accept(2)
EOPNOTSUPP
The referenced socket is not of type SOCK_STREAM.
There are no connections in UDP, so there is nothing to accept. Once you have bound a UDP socket to a port, you can start calling recvfrom() and sendto() on it.
In order to connect an IRC client to this server code, you need to change the socket type to SOCK_STREAM. IRC runs on TCP, not on UDP.
I have application which uses sockets to transfer data between two clients. It uses a single socket to communicate control and data traffic (over UDP).
Qos and tos fields of IP header can be changed using
setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos, toslen);
setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, &cos, coslen);
But how many calls to setsockopt (to the same socket) is too many?
For example, lets assume it will be called every 1ms.
To narrow question scope, I am asking about modern linux system (generic explanation is more than welcomed).
Here is an example to demonstrate it (this is the sending-only part of the application):
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define NPACK 10000
#define PORT 44444
#define BUFLEN 128
void diep(char *s) {
perror(s);
exit(1);
}
#define SRV_IP "12.34.56.78"
int main(void) {
struct sockaddr_in si_other, si_me;
int s, i, slen = sizeof(si_other);
int toss[2] = { 56, 160 }, coss[] = { 1, 3 };
char buf[BUFLEN];
//Create UDP socket
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
diep("socket");
//Create remote socket
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr) == 0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
//Create local socket and bind to it.
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, &si_me, sizeof(si_me)) == -1)
diep("bind");
//Loop on number of packets
for (i = 0; i < NPACK; i++) {
sprintf(buf, "This is packet %d, %d\n", i, toss[i % 2]);
printf("Sending packet %d. %s", i, buf);
//Change tos and cos. odd packets high priority , even packets low priority.
setsockopt(s, IPPROTO_IP, IP_TOS, &toss[i % 2], sizeof(int));
setsockopt(s, SOL_SOCKET, SO_PRIORITY, &coss[i % 2], sizeof(int));
//Send!
if (sendto(s, buf, strlen(buf), 0, &si_other, slen) == -1)
diep("sendto()");
}
close(s);
return 0;
}
NOTES:
Both control and data should share the same socket (same UDP source port).
Multiple threads will use the same socket (so some locking mechanism needed between setsockopt and sendto; but this is outside the scope of the question).
SO_PRIORITY is linux only.
This is my code which can run CentOS and Windows just fixing some headers.
#define _WIN32_WINNT 0x0501
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
/*
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
*/
int main()
{
int sock;
int ret = 0;
int port= 12345;
struct sockaddr_in addr;
char buf[1024];
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock<0){
printf("socket() ret = %d : %s\n",ret,strerror(errno));
return ret;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if(ret<0){
printf("bind() ret = %d errno =%d : %s\n",ret,errno,strerror(errno));
return ret;
}
printf("############# Binding port %d type Enter to stop \t",port);
fgets(buf,sizeof(buf),stdin);
return 0;
}
When I tried to bind same port by this program with runing tow process, there must be the messages that Address already in use like below.
[The first proc#centOS ]
$ ./udp
############# Binding port 12345 type Enter to stop
[The second proc#centOS]
$ ./udp
bind() ret = -1 errno =98 : Address already in use
$
However when I do same thing with same code on windows, message is different.
[The first proc#windows]
C:\ >udp
############# Binding port 12345 type Enter to stop
[The second proc#windows]
C:\ >udp
bind() ret = -1 errno =34 : Result too large
C:\ >
How can I get Address already in use on Windows?
I don't think you should use errno on windows for sockets code. You could try to use WSAGetLastError which returns WSAEADDRINUSE.
The MSDN page for errno suggests EADDRINUSE is not supported for errno.
I think you should devise a scheme where you have a my_errno function that depending on the platform uses errno or WSAGetLastError.
printf("socket() ret = %d : %s\n",ret,strerror(errno));
There may be a subtle issue with this call. The order of argument evaluation is unspecified and strerror itself can change errno, which means it has side-effects. You should print errno separately, before doing anything else.
Like cnicular said, you have to use WSAGetLastError() on Windows, not errno. To get a text message for a socket error code, you can use FormatMessage().
To answer your question, if you want to find out who is using the port, you can use the command-line netstat tool, or programmably using GetTcpTable2().
i wrote a client application in c using the posix sockets api on linux that sends information to a server, which then gets printed to the servers terminal window. If the server is on the same machine as the client and the client sends to the loopback or to its own IP address then all is good. However, if the server is running on another machine, then sendto returns an "invalid argument" error.
Here is the code for the client application:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "utils.h" // for 'errexit()'
#define PEER_PORT 54321
#define BUFFSIZE 100
#define local_net_ip "192.168.0.10"
int main( int argc, char *argv[] )
{
int clientfd;
clientfd = socket( AF_INET, SOCK_DGRAM, 0 );
if( clientfd == -1 )
errexit( "socket()" );
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons( PEER_PORT );
if( inet_pton( AF_INET, local_net_ip, (void *) &(servaddr.sin_addr) ) == -1 )
errexit( "inet_pton()" );
char addrStr[ INET_ADDRSTRLEN ];
inet_ntop( servaddr.sin_family, &(servaddr.sin_addr), addrStr, INET_ADDRSTRLEN );
printf("Server IPv4 addr: [ %s ]\n", addrStr);
char buff[ BUFFSIZE ];
int writebytes;
for( ;; ) {
printf( "Enter text: ");
fgets( buff, BUFFSIZE, stdin );
writebytes = sendto( clientfd, buff, BUFFSIZE, 0, (struct sockaddr *) &servaddr, sizeof( struct sockaddr_in ) );
if( writebytes == -1 )
errexit( "sendto()" );
}
exit( EXIT_SUCCESS );
}
I would greatly appreciate any information as to why the application won't send to another computer! Thanks in advance!!
clientfd = socket( AF_INET, SOCK_DGRAM, 0 );
You are creating a socket with protocol 0, e.g. IP. But later you use and IP:Port as a target. You probably wanted to use an UDP socket here (proto 17).