I am trying to create a web-server which will accept requests and commands from sockets (in different ports). I have some demo code for simple socket communication, which compiles and runs as expected, but when I run mine (written with demo as a reference, that is why there are some printf's) accept() fails with :
"invalid argument" as error. I can not find what is wrong.
Any suggestion/correction is appreciated.
Here is my code:
#include <iostream>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <cstring>
#include <cstdlib>
#include <cstddef>
void perror_exit(char *message);
void thread_run();
int main(int argc, char const *argv[])
{
int i, filepos, serving_port=0, command_port=0, thread_num=0;
char *root_dir = (char *)malloc(sizeof(char *));
int serv_sock=0, command_sock=0, new_sock_c, new_sock_s=0;
struct sockaddr_in server,commands;
struct sockaddr_in server_client,commands_client;
struct sockaddr *serverptr=(struct sockaddr *)&server;
struct sockaddr *commandsptr=(struct sockaddr *)&commands;
struct sockaddr *server_clientptr=(struct sockaddr *)&server_client;
struct sockaddr *commands_clientptr=(struct sockaddr *)&commands_client;
socklen_t clientlen_s, clientlen_c;
struct hostent *rem_s, *rem_c;
socklen_t clientlen;
if(argc != 9){
perror("Wrong number of arguments, webServer");
exit(1);
}else{
for (i=0;i<argc;i++){
if (strcmp(argv[i],"-p") == 0){
serving_port = atoi(argv[i+1]);
}
}
for (i=0;i<argc;i++){
if (strcmp(argv[i],"-c") == 0){
command_port = atoi(argv[i+1]);
}
}
for (i=0;i<argc;i++){
if (strcmp(argv[i],"-t") == 0){
thread_num = atoi(argv[i+1]);
}
}
for (i=0;i<argc;i++){
if (strcmp(argv[i],"-d") == 0){
filepos = i+1;
strncpy(root_dir, argv[i+1], strlen(argv[i+1])+1); // +1 to get "\n" too, without +1 seg fault appears
}
}
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(serving_port);
commands.sin_family = AF_INET;
commands.sin_addr.s_addr = htonl(INADDR_ANY);
commands.sin_port = htons(command_port);
if ((serv_sock = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror_exit("Failed to create serving socket");
// return -1;
}
if ((command_sock = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror_exit("Failed to create command socket");
// return -1;
}
if (bind(serv_sock, serverptr, sizeof(server)) < 0)
perror_exit("bind");
printf("Listening for connections to port %d\n", serving_port);
if (bind(command_sock, commandsptr, sizeof(server)) < 0)
perror_exit("bind");
printf("Listening for commands to port %d\n", command_port);
while(true)
{
clientlen_s = sizeof(server_client);
clientlen_c = sizeof(commands_client);
if ((new_sock_s = accept(serv_sock, server_clientptr, &clientlen_s)) < 0)
perror_exit("accept (server)");
if ((new_sock_c = accept(command_sock, commands_clientptr, &clientlen_c)) < 0)
perror_exit("accept (commands)");
if ((rem_s = gethostbyaddr((char *) &server_client.sin_addr.s_addr, sizeof(server_client.sin_addr.s_addr), server_client.sin_family)) == NULL) {
herror("gethostbyaddr"); exit(1);
}
printf("Accepted serving connection from %s\n", rem_s->h_name);
if ((rem_c = gethostbyaddr((char *) &commands_client.sin_addr.s_addr, sizeof(commands_client.sin_addr.s_addr), commands_client.sin_family)) == NULL) {
herror("gethostbyaddr"); exit(1);
}
printf("Accepted command connection from %s\n", rem_c->h_name);
}
/* code */
return 0;
}
void perror_exit(char *message)
{
perror(message);
exit(EXIT_FAILURE);
}
void thread_run()
{
}
Before calling accept, you should call listen.
From accept manual :
EINVAL Socket is not listening for connections, or addrlen is invalid
(e.g., is negative).
You should add before the loop:
listen(serv_sock,5);
listen(command_sock,5);
However in order to not block in the accept call if no connection is pending, you should consider to use select or poll.
This will allow to check if connection is pending before calling accept
Related
I am currently writing a program in linux where:
client sends a "password" to the server
server waits for n people to send the password and records the address of the sender
after n messages are received, a start message is sent back to the senders.
The problem is when I try to send "start" back to the clients I get an Illegal seek error (ERROR in sendto: Illegal seek). And only the first client receives the start message (clientaddrs[0])
Note: after 30 minutes of testing, the error has now become: Address family not supported by protocol.(absolutely nothing in the code has changed)
Here is my code (I've pasted a minimal reproduceable example)
To reproduce the problem:
run the server code with arguments: 8080
enter 2 at the prompt
run the client code on two different with argument: 127.0.0.1 8080
choose two different passcodes and enter them when prompted by the client
Server code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <chrono>
#include <errno.h>
#include <ifaddrs.h>
#define TO_CLI_BUF_SIZE 32
#define FROM_CLI_BUF_SIZE 8
void printAddr(){ // for printing my ip
struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) {
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
}
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
}
int main(int argc, char ** argv){
//seed rand
srand(time(NULL));
int sockfd; // socket
int port; // my port to listen on
struct sockaddr_in serveraddr; // server's address
struct sockaddr_in clientaddrs[4];
socklen_t clientLens[4];
int currentAddrMax = 0;
struct hostent * hostp; //host info
char * hostaddrp; // host adddr string
char toClientBuf[TO_CLI_BUF_SIZE];
char fromClientBuf[FROM_CLI_BUF_SIZE];
if(argc != 2){
perror("usage: file <port>");
exit(1);
}
port = atoi(argv[1]);
// create socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0){
perror("ERROR: opening socket.");
exit(1);
}
//int option = 1;
//setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&option, sizeof(int));
//internet stuff
bzero((char*) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
perror("ERROR on bind");
exit(1);
}
int playerKeys[4];
int playerJoined[4];
printf("(you can enter 1,2,3 or 4)\n");
printf("Enter amount of players: \n");
int amountPlayers = 0;
scanf("%d",&amountPlayers);
// hacky way to clear screen
printf("\033[H\033[J");
printAddr();
printf("PORT: %d\n", port);
printf("player| key| in\n");
for(int i = 0; i < 4; i++){
bool keyExists = true;
while (keyExists == true ){
playerKeys[i] = rand()%10000;
keyExists = false;
for(int j = 0; j < i; j++){
if(playerKeys[i] == playerKeys[j]){
keyExists = true;
}
}
}
printf("%d |%04d|",i+1, playerKeys[i]);
if(playerJoined[i] == 1){
printf(" o\n");
}else{
printf(" x\n");
}
fflush(stdin);
}
for(int i = 0; i < amountPlayers;i++){
bzero(fromClientBuf, FROM_CLI_BUF_SIZE);
int n = recvfrom(sockfd, fromClientBuf,FROM_CLI_BUF_SIZE, 0, (struct sockaddr*) &clientaddrs[currentAddrMax], &(clientLens[currentAddrMax]));
//TODO store senders
if(n>0){
int key = (fromClientBuf[0]-'0')*1000; //TODO change the way keys are extracted.
key += (fromClientBuf[1]-'0')*100;
key += (fromClientBuf[2]-'0')*10;
key += (fromClientBuf[3]-'0');
for (int i = 0; i < 4; i++){
if(playerKeys[i] == key && playerJoined[i] == 0){
playerJoined[i] = 1;
currentAddrMax++;
}
}
printf("\033[H\033[J");
printAddr();
printf("PORT: %d\n", port);
printf("player| key| in\n");
for(int i = 0; i < 4; i++){
printf("%d |%04d|",i+1, playerKeys[i]);
if(playerJoined[i] == 1){
printf(" o\n");
}else{
printf(" x\n");
}
}
// decode key
}
}
//TODO finished waiting for all senders. send them start signal
//MAY BE USEFULL:n = sendto(sockfd, toClientBuf, strlen(toClientBuf), 0, (struct sockaddr *) &clientaddr, clientlen);
strcpy(toClientBuf, "start");
for(int j = 0; j < currentAddrMax; j++){
int n = sendto(sockfd, toClientBuf, strlen(toClientBuf), 0, (struct sockaddr *) &clientaddrs[j], (clientLens[j]));
if(n < 0) {
perror("ERROR in sendto");
printf("%d\n",j);
exit(1);
}
}
// wait for connections
//main loop
//set some options
struct timeval read_timeout;
read_timeout.tv_sec = 0;
read_timeout.tv_usec = 100;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,&read_timeout,sizeof(read_timeout)) < 0) {
perror("Error with options");
}
printf("start loop\n");
return 0;
}
client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define FROM_SER_BUF_SIZE 32
#define TO_SER_BUF_SIZE 8
int main(int argc, char **argv){
int sockfd, portno, n;
socklen_t serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
char *hostname;
char toServerBuf[TO_SER_BUF_SIZE];
char fromServerBuf[FROM_SER_BUF_SIZE];
if (argc != 3) {
perror("usage: filename <hostname> <port>\n");
exit(0);
}
hostname = argv[1];
portno = atoi(argv[2]);
// create socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("ERROR: opening sockets\n");
exit(0);
}
// get host
server = gethostbyname(hostname);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
exit(0);
}
// build server's internet address
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serveraddr.sin_addr.s_addr, server->h_length);
serveraddr.sin_port = htons(portno);
bzero(toServerBuf, TO_SER_BUF_SIZE);
int key = 0;
printf("Please enter your key: ");
scanf("%d",&key);
if(key > 9999 || key < 0){
printf("INVALID KEY\n");
exit(1);
}
toServerBuf[0] = key/1000 + '0';
toServerBuf[1] = (key%1000)/100 + '0';
toServerBuf[2] = (key%100)/10 +'0';
toServerBuf[3] = key%10 + '0';
serverlen = sizeof(serveraddr);
n = sendto(sockfd, toServerBuf, strlen(toServerBuf), 0, ( struct sockaddr *) &serveraddr, serverlen);
if (n < 0){
perror("ERROR: sendto\n");
exit(0);
}
//TODO wait for server to get send start signal
bzero(fromServerBuf, FROM_SER_BUF_SIZE);
n = recvfrom(sockfd, fromServerBuf, FROM_SER_BUF_SIZE, 0,( struct sockaddr *) &serveraddr, &serverlen);
printf("wow we got here");
return 0;
}
Turns out it was a problem with g++. No idea why g++ doesn't work however, once I switched to clang all my errors went away. However, clang++ does not work either.
Edit: There was a problem with the clientaddr length found with valgrind. Turns out in the array for client legnths (for my example), we must first initialize it with the line
clientLens[currentAddrMax] = sizeof(clientaddrs[currentAddrMax]);
As Bodo mentions, we must always initialize the client length otherwise there will be unspecified behaviour.
I'm having issues with my connect() method on the client side of my socket programming. I'm not sure if the issue is with my code or my method of running it. I'm running it in two seperate terminal windows - one for the server (which I'm running first) with the command './server 8080' and one for the client with the command './client 4 8080 hello'. When I run my code, the server program stops in the while loop just after the printf("this prints\n") line. I presume this means that it is waiting for a client to connect to it. The client program fails on the connect() call, and prints out my error message "Connection Failed". My code is posted below.
Server Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#define bufsize 1024
void eatZombies(int n){
wait3(NULL,WNOHANG,NULL); // Nom Nom
}
int main(int argc, char *argv[]){
int sock, length, msgsock, status;
struct sockaddr_in server;
pid_t id;
signal(SIGCHLD, &eatZombies);
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(atoi(argv[1])); // this time 1st arg is port#
if(bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Error binding the socket\n");
exit(0);
}
if(listen(server_fd, SOMAXCONN) < 0){
printf("Error listening for connections\n");
exit(0);
}
char buffer[1024] = {0};
char *hello = "Hello from server";
int addrlen = sizeof(server);
while(1){
printf("this prints\n");
int client_fd = accept(server_fd, (struct sockaddr *)&server, (socklen_t*)&addrlen);
printf("this doesnt\n");
if(client_fd < 0){
printf("Error accepting connection\n");
exit(0);
}
// the next call makes a new child process that will actually handle the client.
id = fork();
// when id == 0, this is the child and needs to do the work for the server.
// when if > 0, this is the parent, and it should just loop around,
// when id < 0, we had an error.
if(id > 0){
continue;
}
else if(id < 0){
printf("Error\n");
exit(0);
}
read(client_fd, buffer, 1024);
printf("%s\n", buffer);
write(client_fd, hello, strlen(hello), 0);
printf("Hello message sent\n");
exit(0);
}
return 0;
}
Client Code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define bufsize 1024
int main(argc, argv) int argc; char *argv[];{
int sock, rval;
struct hostent *host;
struct sockaddr_in server; // not a pointer
char buf[bufsize];
printf("%d\n", argc);
if(argc != 4){
printf("usage:\ntcpclient hostname port string\n\n");
return(-1);
}
// look up hostname (server) using DNS
if ((host = gethostbyname(argv[1])) == 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
return(-1);
}
// Set up fields for socket to point to host and port
bcopy(host->h_addr, &server.sin_addr, host->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
// Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("Socket Creation Failed\n");
exit(0);
}
// connect (3-way handshake)
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0){
printf("Connection Failed\n");
exit(0);
}
// Copy the arg into buf so we can send it to the server
strncpy(buf, argv[3], bufsize);
// Send sentence to server
send(sock, buf, strlen(buf), 0);
printf("Message sent\n");
// read response from server
rval = read(sock, buf, bufsize);
// print result to window
fprintf(stdout,"%s\n", buf);
close(sock);
}
When running ./client 4 8080 hello, 4 is the host name. You meant to call ./client localhost 8080 hello.
So it was just a mistake in calling the application, not in the code.
I'm trying to build a little personal DHCP server to serve a specific scope if the broadcast is received on eth0 and another if received on wlan0 but I can't bind more than a single interface on the same address:port combination (255.255.255.255:67)
I heard about SO_REUSABLE but I have no idea about how to implement it and if of course it's the good way to do it
Actually this is my code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <vector>
#define BUFLEN 1024
#define PORT 67
using namespace std;
char *ipAddrFromInterface(char *apInterfaceName) //this function is not from me
{
return "255.255.255.255";
/*char *if_name = (char *) apInterfaceName;
struct ifreq ifr;
size_t if_name_len = strlen(if_name);
if(if_name_len < sizeof(ifr.ifr_name))
{
memcpy(ifr.ifr_name, if_name, if_name_len);
ifr.ifr_name[if_name_len] = 0;
}
else
printf("interface name is too long\n");
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd == -1)
printf("A => %s\n", strerror(errno));
if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
{
int temp_errno = errno;
close(fd);
printf("B => %s\n", strerror(temp_errno));
}
if(ioctl(fd, SIOCGIFADDR, &ifr) == -1)
{
int temp_errno = errno;
close(fd);
printf("C => %s\n", strerror(temp_errno));
}
close(fd);
struct sockaddr_in* ipaddr = (struct sockaddr_in*) &ifr.ifr_addr;
return inet_ntoa(ipaddr->sin_addr);*/
}
struct socketData
{
int sock;
sockaddr_in socket;
char *interfaceName;
};
void print(int i)
{
printf("%d\n", i);
fflush(stdout);
}
void server_receive_thread(vector<char*> aInterfaceList)
{
int socketIndex = 0;
struct sockaddr_in localSock;
int socketDescriptor; int socketLength;
vector<socketData> aSockets;
for( ; socketIndex < aInterfaceList.size(); socketIndex++)
{
socketData socketD;
char *apInterfaceName = aInterfaceList.at(socketIndex);
if((socketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
printf("can't listen on interface %s... sleeping\n", apInterfaceName);
}
else
{
memset(&localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(PORT);
inet_aton(ipAddrFromInterface(apInterfaceName), &localSock.sin_addr);
setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE, apInterfaceName, sizeof(apInterfaceName));
if(bind(socketDescriptor, (struct sockaddr *) &localSock, sizeof(localSock)) == -1)
{
printf("can't bind interface %s to listen on port %d... sleeping\n", apInterfaceName, PORT);
}
else
{
printf("bound to interface %s on port %d\n", apInterfaceName, PORT);
socketD.sock = socketDescriptor;
socketD.socket = localSock;
socketD.interfaceName = apInterfaceName;
aSockets.push_back(socketD);
}
}
}
fd_set master;
int fdMax = -1;
while(1)
{
FD_ZERO(&master);
for(int iSock = 0; iSock < aSockets.size(); iSock++)
{
socketData d = aSockets.at(iSock);
FD_SET(d.sock, &master);
if(d.sock > fdMax)
fdMax = d.sock;
}
printf("fdmax is : ");
print(fdMax);
if(select(fdMax + 1, &master, NULL, NULL, NULL) == -1)
print(2);
print(200);
for(int iSock = 0; iSock < aSockets.size(); iSock++)
{
socketData d = aSockets.at(iSock);
if(FD_ISSET(d.sock, &master))
print(3);
}
print(1);
}
}
int main()
{
std::vector<char*> interfaceList;
interfaceList.push_back("wlan0");
interfaceList.push_back("eth0");
server_receive_thread(interfaceList);
return 0;
}
You don't need a socket per interface. Just bind a single socket to 0.0.0.0 and the desired port. Then it will receive via all interfaces. You certainly can't, and don't need to, bind to 255.255.255.255.
Or, bind it to the single IP address that is connected to the scope you want to serve.
this is client server application I want to establish SIP (session initiation protocol) between client and server.
So please anyone guide me how can I do this.
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netinet/tcp.h>
#define MYPORT 3490 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXDATASIZE 100
void str_server(int);
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(void)
{
int sockfd, numbytes,new_fd, optlen; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
struct tcp_info info;
socklen_t sin_size;
struct sigaction sa;
char buf[MAXDATASIZE];
int yes=1;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
while(1) { // main accept() loop
sin_size = sizeof their_addr;
getchar();
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
&sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n", \
inet_ntoa(their_addr.sin_addr));
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if ((numbytes=recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received From Client: %s\n",buf);
str_server(sockfd);
FILE *fp = fopen( "adventure.mpg", "rb" );
//if(!fork())
// execlp("gedit", "gedit", "SIPFILE.txt", NULL);
//system("popen /home/umair/Documents/CurrentData/SIPFILE.txt");
//ShellExecute(GetDesktopWindow(), "open","ls /home/umair/Documents
/CurrentData/SIPFILE.txt",NULL, NULL, SW_SHOW);
if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
void str_server(int sock)
{
char buf[1025];
const char* filename = "test.text";
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("Can't open file for reading");
return;
}
while (!feof(file))
{
int rval = fread(buf, 1, sizeof(buf), file);
if (rval < 1)
{
printf("Can't read from file");
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(sock, &buf[off], rval - off, 0);
if (sent < 1)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes writable
// again before failing the transfer...
printf("Can't write to socket");
fclose(file);
return;
}
off += sent;
}
while (off < rval);
}
fclose(file);
}
//client.c :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#define PORT 3490 // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
void RecvFile(int , const char* );
FILE *filename;
int main(int argc, char *argv[])
{
int sockfd, numbytes, optlen;
char buf[MAXDATASIZE];
char *message;
struct hostent *he;
struct tcp_info info;
struct sockaddr_in their_addr; // connector's address information
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(PORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
if (connect(sockfd, (struct sockaddr *)&their_addr,
sizeof their_addr) == -1) {
perror("connect");
exit(1);
}
printf("connect successfull\n");
/* if (send(sockfd, "Hello, world!\n", 14, 0) == -1)
perror("send");
printf("send successfull\n");
*/
message = "GET /?st=1 HTTP/1.1\r\nHost: www.msn.com\r\n\r\n";
if( send(sockfd , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");
RecvFile(sockfd , message);
optlen = sizeof(info);
if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received: %s\n",buf);
close(sockfd);
return 0;
}
void RecvFile(int sock, const char* filename)
{
int rval;
char buf[0x1000];
FILE *file = fopen(filename, "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
}
while (!feof(file));
fclose(file);
}
Any Suggestion?
I am not sure what you are trying to do with SIP, but the code snippet you've provided shows only establishing a TCP/IP connection. If you intend to do a SIP server-client application, I suggest that you look for a library to help you along the way.
One that I know of that is very complete is called Sofia SIP:
http://sofia-sip.sourceforge.net/
It's written by Nokia for Linux in C language.
Source code is available here: http://gitorious.org/sofia-sip/sofia-sip/trees/master
(Older http://sourceforge.net/p/sofia-sip/git/ci/master/tree/)
you can learn about sipp scenarios and message passing through this utility and its documentation.
I'm new to socket programming and I have this client that tries to connect to a server on the same computer. But the server hangs there after bind or accept—cause bind seems to be right but no output. I know that the server works because another client can connect just fine and the client seems to have done that. What causes the server to not see this incoming connection? I'm at the end of my wits here.
And I haven't been used to programming on Mac, so thank you so much for your patience if I have made some foolish mistakes.
My code is as follows:
server.cpp
using namespace std;
#include<iostream>
#include <netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define PORT 8888
#define BACKLOG 20
//#define DEST_IP "127.0.0.1"
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
int main(int argc,char *argv[])
{
//cout<<"?";
int ss, sc, r, err;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int opt=1;
pid_t pid;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
ss = socket(AF_INET, SOCK_STREAM, 0);
if(ss<0)
{
cout<<"[process infro]socket error"<<endl;
return -1;
}
cout<<"[process infro]socket successful"<<endl;
r = setsockopt(ss, SOL_SOCKET,SO_REUSEADDR, (void*)&opt,sizeof(opt));
if (r == -1)
{
perror("setsockopt(listen)");
return 0;
}
cout<<"[process infro]sockopt successful"<<endl;
cout<<"?";
err = bind(ss, (struct sockaddr*) &server_addr, sizeof( server_addr));
cout<<"err";
if(err < 0)
{
cout<<"[process infro]bind error"<<endl;
return -1;
}
cout<<"[process infro]bind successful";
err=listen(ss, BACKLOG);
if(err <0)
{
cout<<"[process infro]listen error"<<endl;
return -1;
}
cout<<"[process infro]lisen successful";
for( ; ; )
{
int addrlen = sizeof(struct sockaddr);
sc = accept(ss, (struct sockaddr*)&client_addr, (socklen_t *)&addrlen);
if(sc < 0)
{
continue;
}
pid = fork();
if (pid == 0)
{
close(ss);
process_conn_server(sc);
}
else
{
close(sc);
}
}
//opt=0;
//setsockopt(ss,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(len));
}
client.cpp
using namespace std;
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <time.h>
#include <arpa/inet.h>
#include <fstream.h>
#define PORT 8888
#define DEST_IP "127.0.0.1"
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
write(s,buffer,1024);
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close(); //关闭文件
}
int main(int argc,char *argv[])
{
int s;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(DEST_IP);
server_addr.sin_port = htons(PORT);
s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0)
{
cout<<"[process infro]socke error"<<endl;
return -1;
}
cout<<"[process infro] socket built successfully\n";
//inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
cout<<"[process infor] connected\n";
process_conn_client(s);
close(s);
return 0;
}
This may be unrelated.... but it won't fit in a comment...
In your server you do this:
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
// keep reading until read returns 0
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
In your client you do this:
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
// write to server?
write(s,buffer,1024);
// read from server?
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close();
}
It's a bit hard to follow because of your variable names, but it looks like your client is working under the assumption that your server will send back a response for every chunk of data received, which isn't the case. You server doesn't appear to have changed the accepted socket to non-blocking, so it's going to block on the read call until there is some data to read (it's never going to get 0)...
Are you sure it's failing before this point? Do you have some sample output?
Aso, in your call to accept, you pass addrlen...
int addrlen = sizeof(struct sockaddr);
I think this should be:
int addrlen = sizeof(struct sockaddr_in); /* sizeof(client_addr) */