I know this is kinda lame question, but what am I doing wrong in my code ? Basically, I wanna create communication on local IP using UDP, also send some files etc. The problem is, that when I get to freeing my structures after using them/converting them to/from char* the program just crashes. What is even more weird, the program does not crash when debugging and stepping through using CLion debugger. What am I doing wrong? Here is my source code:
The error seems to happen, when I can not allocate more memory (so logically, I need to free some) when sending a file over network. Sending messages works just fine
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
// PKS2Visual.cpp : Defines the entry point for the console application.
//
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <time.h>
#define BREAKSOMETHING 0
#pragma comment(lib, "ws2_32.lib")
int fragSize = 1500;
int isInside = 0;
SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;
int main() {
char mode;
printf("Enter fragment size:\n");
scanf("%d", &fragSize);
p2pMode();
}
DWORD WINAPI receiveThreadFunc(LPVOID lpParam) {
int slen = sizeof(otherClient);
int doRun = 1;
int sizee;
char msgBuffer[1519];
char fileName[1519];
int receivingFile = 0;
while (doRun) {
printf("Waiting for data...\n\n");
if ((recvfrom(s1, msgBuffer, 1519, 0, (struct sockaddr *) &otherClient,
&slen)) == SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
//printf("Received packet from %s:%d\n", inet_ntoa(otherClient.sin_addr), ntohs(otherClient.sin_port));
PacketData *packetData = dataToPacket(msgBuffer);
if (packetData == NULL) {
continue;
}
char flag = packetData->flag;
switch (flag) {
case 's': {
PacketData *packetDataAck = createPacket('a');
char *messageToSend2 = packetToData(packetDataAck, &sizee);
if (sendto(s1, messageToSend2, 18, 0, (struct sockaddr *) &otherClient, slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
//free(packetDataAck);
//free(messageToSend2);
break;
}
case 'm': {
if (receivingFile) {
FILE *fptr;
fptr = fopen(fileName, "a");
fprintf(fptr, "%s", packetData->data);
printf("Packet contains data: %s\n", packetData->data);
fclose(fptr);
if(packetData->fragNum == packetData->fragTotal){
receivingFile = 0;
}
} else {
printf("Received packet n. %d\n", packetData->fragNum);
printf("Packet data length: %d\n", packetData->len);
printf("Packet contains data: %s\n", packetData->data);
}
break;
}
case 'f': {
strcpy(fileName, packetData->data);
printf("Receiving file: %s\n", fileName);
printf("Receiving file: %s\n", packetData->data);
receivingFile = 1;
break;
}
default: {
doRun = 0;
break;
}
}
free(packetData);
}
return 0;
}
DWORD WINAPI sendThreadFunc(LPVOID lpParam) {
PacketData **fragments = NULL;
int doRun = 1;
char msgBuffer[1500];
int actualSize = 0;
int slen = sizeof(myClient);
while (1) {
printf("Enter message or -e to end messaging and return to menu:\n");
fflush(stdin);
scanf("%1500[^\n]", msgBuffer);
getc(stdin);
if (strcmp(msgBuffer, "-e") == 0) {
isInside = 0;
return 0;
}
if (strlen(msgBuffer) >= 1499) {
continue;
}
fragments = makeFragments(msgBuffer);
int numFragments = fragments[0]->fragTotal;
printf("Number of fragments: %d\n", numFragments);
PacketData *packetData = createPacket('s');
if (packetData == NULL) {
printf("Could not init packet 's'\n");
continue;
}
char *sync = packetToData(packetData, &actualSize);
if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("First fragment sent.\n");
free(packetData);
char *ack = (char *) calloc(18, sizeof(char));
if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
free(ack);
printf("Server confirmed first packet.\n");
for (int i = 0; i < fragments[0]->fragTotal; i++) {
char *msgBuffer2 = packetToData(fragments[i], &actualSize);
if (sendto(s2, msgBuffer2, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
}
free(fragments);
}
return 0;
}
DWORD WINAPI sendFileFunc(LPVOID lpParam) {
char msgBuffer[1500];
int actualSize = 0;
int slen = sizeof(myClient);
while (1) {
printf("Enter file name or -e to return to menu:\n");
fflush(stdin);
scanf("%1500[^\n]", msgBuffer);
getc(stdin);
if (strcmp(msgBuffer, "-e") == 0) {
isInside = 0;
return 0;
}
if (strlen(msgBuffer) >= 1499) {
continue;
}
//Get file length:
FILE *fl = fopen(msgBuffer, "r");
if (fl == NULL) {
printf("Invalid name, try again\n");
continue;
}
fseek(fl, 0, SEEK_END);
long fileLength = ftell(fl);
fclose(fl);
int numFragments = (fileLength - 1) / fragSize + 2;
printf("Number of fragments: %d\n", numFragments);
PacketData *packetData = createPacket('s');
if (packetData == NULL) {
printf("Could not init packet 's'\n");
continue;
}
char *sync = packetToData(packetData, &actualSize);
if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("First fragment sent.\n");
free(packetData);
char *ack = (char *) calloc(18, sizeof(char));
if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
//free(ack);
PacketData *fragments = NULL;
fragments = (PacketData *) malloc(sizeof(PacketData));
fragments->data = (char *) malloc(fragSize * sizeof(char));
strncpy(fragments->data, msgBuffer, strlen(msgBuffer));
fragments->data[strlen(msgBuffer)] = '\0';
fragments->flag = 'f';
fragments->len = strlen(msgBuffer);
fragments->fragNum = (unsigned int) (1);
fragments->fragTotal = (unsigned int) numFragments - 1;
fragments->CRC = (unsigned int) calculate_crc(msgBuffer, strlen(msgBuffer));
//Sending the first fragment with 'f' flag
char *toSend = packetToData(fragments, &actualSize);
if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("Server confirmed first packet.\n");
size_t n = 0;
int counter = 0;
int fragNum = 2;
int c;
FILE *f2 = fopen(msgBuffer, "r");
if(f2 == NULL){
printf("File was null\n");
continue;
}
while ((c = fgetc(f2)) != EOF) {
msgBuffer[n++] = (char) c;
counter++;
if (counter == fragSize) {
n = 0;
counter = 0;
printf("Allocating fragment number: %d\n", fragNum);
PacketData *fragments2 = NULL;
fragments2 = (PacketData *) malloc(sizeof(PacketData));
if(fragments2 == NULL){
printf("Incorrect malloc\n");
break;
}
fragments2->data = (char *) malloc((fragSize+1) * sizeof(char));
if(fragments2->data == NULL){
printf("Incorrect malloc2\n");
break;
}
strncpy(fragments2->data, msgBuffer, fragSize);
printf("Copying data to fragment number: %d\n", fragNum);
fragments2->data[strlen(msgBuffer)] = '\0';
fragments2->flag = 'm';
fragments2->len = (unsigned int) fragSize;
fragments2->fragNum = (unsigned int) (fragNum);
fragments2->fragTotal = (unsigned int) numFragments - 1;
fragments2->CRC = (unsigned int) calculate_crc(msgBuffer, fragSize);
printf("Allocated fragment number: %d\n", fragNum);
fragNum++;
char *toSend = packetToData(fragments2, &actualSize);
if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("Sent fragment number: %d\n", fragNum);
}
}
fclose(fl);
}
return 0;
}
void p2pMode() {
int serverPort, clientPort;
char *serverAddr = (char *) malloc(20 * sizeof(char));
WSADATA wsa;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("Failed. Error Code : %d", WSAGetLastError());
getchar();
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
char hostname[128] = "";
char menuBuffer;
gethostname(hostname, sizeof(hostname));
struct hostent *ent = gethostbyname(hostname);
struct in_addr ip_addr = *(struct in_addr *) (ent->h_addr);
printf("Your IP Address: %s\n", inet_ntoa(ip_addr));
printf("Enter other PC IP Address:\n");
scanf("%s", serverAddr);
if (!strcmp(serverAddr, "localhost"))
serverAddr = (char *) "127.0.0.1";
printf("Enter your listening port:\n");
scanf("%d", &clientPort);
printf("Enter other PC's port:\n");
scanf("%d", &serverPort);
if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket : %d", WSAGetLastError());
}
if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(inet_ntoa(ip_addr));
server.sin_port = htons(clientPort);
myClient.sin_family = AF_INET;
myClient.sin_port = htons(serverPort);
myClient.sin_addr.S_un.S_addr = inet_addr(serverAddr);
if (bind(s1, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
free(serverAddr);
DWORD dwThreadId, dwThreadId2, dwThreadId3, dwThrdParam = 1;
CreateThread(
NULL, // default security attributes
10000, // use default stack size
receiveThreadFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
while (1) {
if (!isInside) {
printf("For messages, write 'm', for file 'f'\n");
scanf("%c", &menuBuffer);
switch (menuBuffer) {
case 'm':
CreateThread(
NULL, // default security attributes
10000, // use default stack size
sendThreadFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId2); // returns the thread identifier
isInside = 1;
break;
case 'f':
CreateThread(
NULL, // default security attributes
10000, // use default stack size
sendFileFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId3); // returns the thread identifier
isInside = 1;
break;
}
}
}
}
char *packetToData(PacketData *packet, int *size) { // convert packet into sendable data
int sizee = packet->len + 18;
*size = sizee;
char *temp = (char *) calloc(sizee, sizeof(char));
char *out;
if (temp == NULL) {
return NULL;
}
out = temp;
*(temp) = packet->flag;
*(unsigned int *) (temp + 2) = packet->CRC;
*(unsigned int *) (temp + 6) = packet->fragNum;
*(unsigned int *) (temp + 10) = packet->fragTotal;
*(unsigned int *) (temp + 14) = packet->len;
temp = (temp + 18);
int i;
for (i = 0; i < packet->len; i++) { // copy data
temp[i] = packet->data[i];
}
temp[i] = '\0';
return out;
}
PacketData *dataToPacket(char *data) { // convert received data into packet
printf("Data received: %s\n", data);
PacketData *packet = (PacketData *) malloc(sizeof(PacketData));
if (packet == NULL)
return NULL;
packet->flag = *(data);
packet->CRC = *(unsigned int *) (data + 2);
packet->fragNum = *(unsigned int *) (data + 6);
packet->fragTotal = *(unsigned int *) (data + 10);
packet->len = *(unsigned int *) (data + 14);
packet->data = (char *) malloc(packet->len);
char *packetdata = (data + 18);
int i;
for (i = 0; i < packet->len; i++) { // copy data
packet->data[i] = packetdata[i];
}
packet->data[i] = '\0';
return packet;
}
PacketData *createPacket(char flag) {
PacketData *packetData = (PacketData *) malloc(sizeof(PacketData));
packetData->flag = flag;
packetData->len = 0;
packetData->CRC = 0;
packetData->fragNum = 1;
packetData->fragTotal = 1;
return packetData;
}
int calculate_crc(char *buf, int size) {
int crcHash = 10;
for (int i = 0; i < size; i++) {
crcHash += buf[i];
crcHash *= 31;
crcHash %= 30000;
}
return crcHash;
}
struct packetData **makeFragments(char *message) {
int i;
printf("Message length: %d\n", strlen(message));
int fragCount = (strlen(message) - 1) / fragSize + 1;
if (fragCount == 0) {
fragCount++;
}
PacketData **fragments = (PacketData **) malloc((fragCount) * sizeof(PacketData *));
printf("Allocated %d fragments\n", fragCount);
for (i = 0; i < fragCount; i++) {
fragments[i] = (PacketData *) malloc(sizeof(PacketData));
fragments[i]->data = (char *) malloc(fragSize * sizeof(char));
int toCopy = 0;
if (strlen(message) > fragSize) {
toCopy = fragSize;
} else {
toCopy = strlen(message);
}
strncpy(fragments[i]->data, message, toCopy);
fragments[i]->data[toCopy] = '\0';
fragments[i]->flag = 'm';
fragments[i]->len = (unsigned int) toCopy;
fragments[i]->fragNum = (unsigned int) (i + 1);
fragments[i]->fragTotal = (unsigned int) fragCount;
fragments[i]->CRC = (unsigned int) calculate_crc(message, toCopy);
message += fragSize;
}
printf("Fragments needed: %d\n", fragments[0]->fragTotal);
return fragments;
}
and here is my header if someone needed to run it:
//
// Created by lukas on 11/19/2018.
//
#include <winsock2.h>
#include <windows.h>
#ifndef PKS2C_MAIN_H
#define PKS2C_MAIN_H
#endif //PKS2C_MAIN_H
typedef struct packetData {
char flag;
unsigned int CRC;
unsigned int fragNum;
unsigned int fragTotal;
unsigned int len;
char *data;
} PacketData;
struct packetData **makeFragments(char *message);
struct packetData **makeFileFragments(char *message);
char *packetToData(PacketData *packet, int *size);
PacketData *dataToPacket(char *data);
PacketData *createPacket(char flag);
void p2pMode();
int calculate_crc(char *buf, int size);
DWORD WINAPI receiveThread(LPVOID lpParam);
DWORD WINAPI sendThread(LPVOID lpParam);
SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;
Related
I am using the following code to receive SCTP notifications. I am using Linux ubuntu 20.04.
Please could you help to intercept SACK_SCTP messages. Here you find attached my code to receive all possible notifications.
void *
receive_sacks(void *arg)
{
sockParamRcv_t paramsDest = *((sockParamRcv_t *) arg);
char buffer[100];
int ret;
int flags = 0;
struct sctp_sndrcvinfo info;
union sctp_notification *notification;
struct sctp_event_subscribe events;
socklen_t from_len = sizeof(paramsDest.servaddr.sin_addr);
// Set the events of interest for the socket
memset(&events, 0, sizeof(events));
events.sctp_data_io_event = 1;
events.sctp_association_event = 1;
events.sctp_adaptation_layer_event = 1;
events.sctp_send_failure_event = 1;
events.sctp_assoc_reset_event = 1;
events.sctp_stream_change_event = 1;
events.sctp_stream_reset_event = 1;
events.sctp_shutdown_event = 1;
events.sctp_send_failure_event = 1;
ret = setsockopt(paramsDest.sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events));
if (ret < 0) {
perror("setsockopt");
return 1;
}
while (1) {
ret = sctp_recvmsg(paramsDest.sock, buffer, sizeof(buffer), (struct sockaddr *) NULL, 0, &info, &flags);
if (ret < 0) {
perror("sctp_get_sndrcvinfo() failed");
close(paramsDest.sock);
exit(1);
}
printf("Received SCTP SACK message, %d\n", info.sinfo_flags);
printf("Received unexpected SCTP message type\n");
if (ret > 0) {
printf("flags : %d\n", flags);
printf("Received message: %s\n", buffer);
if (flags & MSG_NOTIFICATION) {
notification = (union sctp_notification *) buffer;
printf("flags : %d\n", flags);
}
}
}
return NULL;
}
I'm coding udp server, which can listen multiple ports. As the method of paralleling I use function poll(). So server get two ports in argc, and then try to listen the range of ports. Then open msg.txt, where saves all the information, which he get from clients. A then waiting for them. But the problem is that with poll(), my server can listen only one port. But if I delete this function, server accept messages from all ports. What can be a problem?Here's my code:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/poll.h>
int set_non_block_mode(int s)
{
int fl = fcntl(s, F_GETFL, 0);
return fcntl(s, F_SETFL, fl | O_NONBLOCK);
}
void s_close(int s)
{
close(s);
}
int sock_err(const char *function, int s)
{
int err = errno;
fprintf(stderr, "%s: socket error: %d\n", function, err);
return -1;
}
struct client
{
char id[30];
int msgs[20];
struct cl *next;
char send[81];
int amount;
int answer;
};
struct client *addnew(struct client *head)
{
struct client *tmp = (struct client *)calloc(1, sizeof(struct client));
memset(tmp->msgs, 0, 20);
memset(tmp->send, '\0', 81);
memset(tmp->id, '\0', 30);
tmp->amount = 0;
tmp->answer = 0;
tmp->next = NULL;
return tmp;
}
struct client *search(struct client *head, unsigned int ip, int port)
{
char str[30];
sprintf(str, "%u.%u.%u.%u:%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, (ip)&0xFF, port);
struct client *tmp = head;
if (tmp!=NULL){
while (1)
{
if (strcmp(tmp->id, str) == 0)
{
return tmp;
}
if(tmp->next==NULL)break;
tmp = tmp->next;
}
tmp->next = addnew(head);
tmp = tmp->next;
strcpy(tmp->id, str);
return tmp;
} else {
tmp = addnew(head);
strcpy(tmp->id, str);
return tmp;
}
}
int parcing(FILE *text, char *buffer, int s, struct sockaddr_in *addr, struct client *head, int port)
{
int flags = MSG_NOSIGNAL;
int addrlen = sizeof(*addr);
unsigned int ip = ntohl((*addr).sin_addr.s_addr);
struct client *tmp = search(head, ip, port);
int n;
memcpy(&n, buffer, 4);
n = ntohl(n);
if (tmp->msgs[n] == 0)
{
tmp->msgs[n] = 1;
tmp->answer++;
n = htonl(n);
memcpy(&tmp->send[4 * tmp->amount], tmp->send, 4 * tmp->amount);
tmp->amount++;
memcpy(tmp->send, &n, 4);
fprintf(text, "%s %d:%d:", tmp->id, buffer[4], buffer[5]);
memcpy(&n, &buffer[6], 2);
n = ntohs(n);
fprintf(text, "%hu ", n);
memcpy(&n, &buffer[8], 2);
n = ntohs(n);
fprintf(text, "%hi ", n);
for (int i = 10; i < 22; i++)
fprintf(text, "%c", buffer[i]);
fprintf(text, " %s\n", &buffer[22]);
sendto(s, tmp->send, 4 * tmp->amount, flags, (struct sockaddr *)addr, addrlen);
if (strcmp(&buffer[22], "stop") == 0)
return 0;
return 1;
}
else
{
sendto(s, tmp->send, 4 * tmp->amount, flags, (struct sockaddr *)addr, addrlen);
}
}
int main(int argc, char *argv[])
{
int i;
int flags = MSG_NOSIGNAL;
int start, end;
if (argc == 3)
{
start = atoi(argv[1]);
end = atoi(argv[2]);
}
else
{
start = atoi(argv[1]);
end = start;
}
//start = 8035;
//end = start;
int AmountOfPorts = end - start + 1;
struct pollfd *pfd = (struct pollfd *)calloc(AmountOfPorts, sizeof(struct pollfd));
int *s = (int *)calloc(AmountOfPorts, sizeof(int));
struct sockaddr_in *addr = (struct sockaddr_in *)calloc(AmountOfPorts, sizeof(struct sockaddr_in));
for (int i = 0; i < AmountOfPorts; i++)
{
s[i] = socket(AF_INET, SOCK_DGRAM, 0);
if (s[i] < 0)
return sock_err("socket", s[i]);
set_non_block_mode(s[i]);
memset(&addr[i], 0, sizeof(addr));
addr[i].sin_family = AF_INET;
addr[i].sin_port = htons(start + i);
addr[i].sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s[i], (struct sockaddr *)&addr[i], sizeof(addr[i])) < 0)
return sock_err("bind", s[i]);
pfd[i].fd = s[i];
pfd[i].events = POLLIN | POLLOUT;
}
int g = 1;
struct client *head = NULL;
struct client *tmp = NULL;
FILE *text = fopen("msg1.txt", "w");
char buffer[131072] = {0};
int addrlen = 0;
do
{
int ev_cnt = poll(pfd, sizeof(pfd) / sizeof(pfd[0]), 100000);
if (ev_cnt > 0)
{
for (i = 0; i < AmountOfPorts; i++)
{
if (pfd[i].revents & POLLHUP)
{
s_close(s[i]);
}
if (pfd[i].revents & POLLERR)
{
s_close(s[i]);
}
if (pfd[i].revents & POLLIN)
{
addrlen = sizeof(addr[i]);
recvfrom(s[i], buffer, sizeof(buffer), 0, (struct sockaddr *)(&addr[i]), &addrlen);
if (rcv > 0)
{
if (!parcing(text, buffer, s[i], &addr[i], head, start + i))
{
g = 0;
break;
}
}
if (pfd[i].revents & POLLOUT)
{
addrlen = sizeof(addr[i]);
unsigned int ip = ntohl((*addr).sin_addr.s_addr);
tmp = search(head, ip, start+i);
sendto(s[i], tmp->send, 4 * tmp->amount, flags, (struct sockaddr *)&addr[i], addrlen);
}
}
}
}
else
{
}
} while (g);
fclose(text);
for (int i = 0; i < AmountOfPorts; i++)
s_close(s[i]);
return 0;
}
You declare pfd as a pointer to a struct pollfd:
struct pollfd *pfd;
Therefore the following construct will not work as intended (for that to work, pfd would have to be an array: struct pollfd pfd[N]):
sizeof(pfd) / sizeof(pfd[0]) //in call to poll
The above expression could be numerically expressed like this (dependend on your machine and os):
//sizeof(struct pollfd*) / sizeof(struct pollfd)
8 / (4 + 2 + 2) => 8 / 8 => 1
//your expectation:
16 / 8 => 2
That means, poll will listen only to the first pollfd, since the parameter nfds is set to 1.
Note: I didn't fully checked your code, but since you're using pointers (calloc) and sizeof a lot, make sure that you did not made the same mistake at other places. Remember pointer != array.
I am using VS2010. Is it possible to make SOCKET global so I can call this socket from all .c files in same project? Is possible, how to do it? If not possible, why not? Below are my codes:
global is where I am creating my global socket. I am using it in main.c and send.c.
global.h
extern SOCKET s;
typedef struct
{
int x;
double y;
char z[32];
}Person;
main.c
#include "stdafx.h"
#include "send.f"
SOCKET s;
void printPerson(Person *p)
{
printf("p.x: %d\n", p->x);
printf("p.y: %f\n", p->y);
printf("p.z: %s\n", p->z);
}
void establishConnection()
{
//extern SOCKET s;
struct sockaddr_in server;
//struct addrinfo hints;
//char *message, server_reply[2000];
//int recv_size;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(200);
if(connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
puts("Connect error");
Sleep(1000);
puts("Retrying");
establishConnection();
}
else
puts("Server Connected\n");
}
int main()
{
char *name;
int a;
WSADATA wsa;
puts("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
puts("Initialized.");
establishConnection();
{
Person p1;
recieveData(&p1);
printPerson(&p1);
printf("\n");
}
{
Person p2;
p2.x = 22;
p2.y = 2.2;
name = "C Plus Plus";
strcpy(p2.z, name);
printPerson(&p2);
sendData(&p2);
}
scanf("%d", &a);
return 0;
}
send.f
void sendData(Person*);
void recieveData(Person*);
send.c
#include "stdafx.h"
void recieveData(Person* p)
{
//extern SOCKET s;
char bufLen[8];
int length, XX;
double YY;
char *msg, *token;
char *ZZ;
if(recv(s, bufLen, 8, 0) < 0)
{
puts("Receive failed");
return;
}
length = atoi(bufLen);
msg = malloc(length + 1);
memset(msg, 0, length + 1);
if (recv(s, msg, length, 0) < 0)
{
puts("Receive failed");
return;
}
printf("Before first token: %s\n", msg);
token = strtok(msg, ";");
printf("After first token: %s\n", token);
XX = atoi(token);
printf("XX: %d\n", XX);
p->x = atoi(token);
token = strtok(NULL, ";");
printf("After second token: %s\n", token);
YY = atof(token);
printf("YY: %f\n", YY);
p->y = atof(token);
token = strtok(NULL, ";");
printf("After third token: %s\n", token);
ZZ = malloc(strlen(token));
memset(ZZ, 0, 32);
strcpy(ZZ, token);
printf("ZZ: %s\n", ZZ);
memset(p->z, 0, 32);
strcpy(p->z, token);
free(msg);
puts("Received!");
}
void sendData(Person* p)
{
//extern SOCKET s;
char msg[2000], clen[9];
int len;
//char *msg;
//msg = malloc(2000);
sprintf(msg, "%d;%f;%s", p->x, p->y, p->z);
len = strlen(msg);
sprintf(clen, "%08d", len);
if (send(s, clen, 8, 0) < 0)
{
puts("Send failed");
return;
}
if (send(s, msg, len, 0) < 0)
{
puts("Send failed");
return;
}
puts("Sent!\n");
}
stdafx.h
#pragma once
#include <tchar.h>
#include "global.h"
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
Your global.h is trying to use SOCKET, which is undeclared at that point. You're missing an #include (probably <winsock2.h>) in global.h.
I am running a client which sends from the command line a timezone, and a test server (which we know works), returns the date and time for that timezone. However after returning the timezones, correctly, it segfaults.
Below is my client code:
int main(int argc, const char * argv[]){
char buf[kBufSize+1];
char line[128];
ssize_t n;
int i;
int more;
int x = 0;
int sockFD;
int port;
struct sockaddr_in sad;
struct hostent *ptrh;
sockFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&sad, 0, sizeof(sad)); /* Sets every byte of the address to be zero */
sad.sin_family = AF_INET;
/* Look up name */
ptrh = gethostbyname(argv[1]);
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Set port */
//sscanf(argv[2], "%d", &port);
port = atoi(argv[2]);
//printf("%d",port);
sad.sin_port = htons(port);
int clifd = connect(sockFD, (struct sockaddr *)&sad, sizeof(sad));
if(clifd < 0) {
printf("[ERROR]: Error Connecting...\n");
return 0;
}
printf("Number of args: %d\n", argc);
x = 3;
//printf("Value of x: %d\n", x);
//printf("[DEBUG]: Value of X: %d\n", x);
//printf("[DEBUG]: Line: %s\n", line);
do
{
/* Read input line */
do
{
more = 1;
n = read(sockFD, buf, kBufSize);
buf[n] = '\0'; // BUF IS READ FROM THE SERVER
if(n <= 0)
break;
for(i = 0; i < n; i++)
{
if(buf[i] == 10)
{
more = 0;
break;
}
}
printf("%s", buf);
if (buf == "BYE\r\n"){
printf("Closing\n");
exit(1);
}
} while(more);
if(n <= 0)
{
break;
}
strcpy(line, argv[x]);
strcat(line, "\r\n\0"); // LINE IS SENT TO THE SERVER
//printf("[DEBUG] Being sent: %s", line);
write(sockFD, line, strlen(line));
//printf("%d", n);
//printf("Value of x: %d\n", x);
x++;
} while (n != 0 && x <= argc);
close(sockFD);
return 0;
}
The argv array goes from 0 to argc-1 but you are using argv from 3 to argc. Look at the condition on your outer do/while loop.
I am writing a C HTTP server for a class. I have a rough implementation working, but I am stuck on this issue. I am trying to multi-thread the GET requests sent from a browser, but the server is just closing the connection after ~10 requests.
Here is the code:
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define SERVPORT 5004
#define BUFSIZE 4096
#define MAXCONNECT 3
#define MAX_THREADS 8
struct data
{
int i;
};
void * clientHandler(void *info);
void sendError(char *msg);
char * getDate();
int sendall(int send_socket, char *buf, int *len);
int parseSrc(char src[]);
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen);
char date[100];
char http200[50] = "HTTP/1.1 200 OK\n";
char http400[50] = "HTTP/1.1 400 Bad Request\n";
char http404[50] = "HTTP/1.1 404 Not Found\n";
int main()
{
printf("Starting server..\n");
int servSock, clntSock, fd;
struct sockaddr_in server, client;
unsigned int len, clntSize;
fd_set master;
fd_set read_fds;
int fdmax;
int i;
if( (servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
sendError("socket");
FD_ZERO(&master);
FD_ZERO(&read_fds);
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERVPORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
for(i=0; i<=10; i++)
{
printf("Trying port %d...\n", (ntohs(server.sin_port) + i));
if( bind(servSock, (struct sockaddr *)&server, sizeof(server)) == -1)
server.sin_port = htons(SERVPORT + i);
else if(i < 10)
break; //socket connected succesfully
else
sendError("bind");
}
printf("Successfully bound to port %d!\n", ntohs(server.sin_port));
if( listen(servSock, MAXCONNECT) == -1)
sendError("listen");
printf("Listening...\n");
FD_SET(servSock, &master);
fdmax = servSock;
pthread_t threads[MAX_THREADS];
while(1)
{
read_fds = master;
int num_threads = 0;
if( select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1)
sendError("select");
for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{
if(i == servSock)
{
clntSize = sizeof(client);
if( (clntSock = accept(servSock, (struct sockaddr *)&client, &clntSize)) == -1)
sendError("accept");
FD_SET(clntSock, &master);
if(clntSock > fdmax)
fdmax = clntSock;
char s[50];
printf("Connected to %s\n", get_ip_str((struct sockaddr *)&client, s, sizeof(s)));
}
else
{
//clientHandler(i);
struct data *info;
info = malloc(sizeof(struct data));
info->i = i;
if(pthread_create(&threads[i], NULL, (void *)clientHandler, (void *)info))
sendError("pthread");
num_threads++;
}
}
}
if(num_threads > MAX_THREADS)
{
num_threads = 0;
pthread_join(threads[num_threads], NULL);
}
}
for(i = 0; i < MAX_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
}
void *clientHandler(void *info)
{
struct data *myinfo = (struct data*) info;
int clntSock = myinfo->i;
char buf[BUFSIZE];
int recd;
if( (recd = recv(clntSock, buf, BUFSIZE, 0)) == -1)
sendError("recieve1");
while(recd > 0)
{
char cmd[5] = "/0";
char src[100] = "/0";
char prt[100] = "/0";
memset(&cmd, 0, sizeof(cmd));
memset(&src, 0, sizeof(src));
memset(&prt, 0, sizeof(prt));
sscanf(buf, "%4s%99s%99s", cmd, src, prt);
char cmdget[5] = "GET";
if(strcmp(cmd, cmdget) == 0) //GET command
{
int len;
if(src[0] == '/')
memmove(src, src+1, strlen(src));
if(strlen(src) == 0)
strcpy(src, "index.html");
FILE *fp;
fp = fopen(src, "r");
if(fp == NULL)
{
len = strlen(http404);
if(sendall(clntSock, http404, &len) == -1)
sendError("send 404");
break;
}
struct stat buf;
fstat(fileno(fp), &buf);
char contLen[50] = "Content-Length: ";
sprintf(contLen, "%s%d\n", contLen, (int)buf.st_size);
char contType[100] = "Content-Type: ";
char *tempType;
tempType = strrchr(src, '.');
if(strcmp(tempType, ".html") == 0) //.html
strcat(contType, "text/html\n");
else if(strcmp(tempType, ".txt") == 0) //.txt
strcat(contType, "text/txt\n");
else if(strcmp(tempType, ".css") == 0) //.css
strcat(contType, "text/css\n");
else if(strcmp(tempType, ".jpg") == 0) //.jpg
strcat(contType, "image/jpg\n");
else if(strcmp(tempType, ".png") == 0) //.png
strcat(contType, "image/png\n");
else if(strcmp(tempType, ".gif") == 0) //.gif
strcat(contType, "image/gif\n");
else if(strcmp(tempType, ".js") == 0) //.js
strcat(contType, "application/javascript\n");
else
{
char fileErrorTemp[50] = "Unknown filetype: ";
strcat(fileErrorTemp, tempType);
sendError(fileErrorTemp);
}
char tempDate[100] = "";
strcpy(tempDate, getDate());
char tempMsg[500] = "";
strcat(tempMsg, http200);
strcat(tempMsg, tempDate);
strcat(tempMsg, contType);
strcat(tempMsg, contLen);
strcat(tempMsg, "\n");
len = strlen(tempMsg);
if( sendall(clntSock, tempMsg, &len) == -1)
sendError("send 200");
printf("Sent client: %s # %s", http200, tempDate);
printf(" Sending %s\n", src);
if( sendfile(fp, clntSock) == -1)
sendError("file send");
}
else //Unknown or bad command
{
int http400len = strlen(http400);
if( send(clntSock, http400, strlen(http400), 0) == -1)
sendError("send 400");
}
printf("Waiting to receive...\n");
if( (recd = recv(clntSock,buf, BUFSIZE, 0)) == -1)
sendError("recieve1");
//printf("%d\n", recd);
}
close(clntSock);
return;
}
void sendError(char *msg)
{
perror(msg);
exit(-1);
}
char * getDate() //return date in "Date: Tue, 16 Feb 2010 19:21:24 GMT" format
{
memset(&date, 0, sizeof(date));
strcpy(date, "Date: ");
time_t rawtime = time(0);
struct tm * info;
time(&rawtime);
info = gmtime(&rawtime);
char wday[5];
char mon[5];
switch(info->tm_wday){
case 0: strcpy(wday, "Mon");
case 1: strcpy(wday, "Tue");
case 2: strcpy(wday, "Wed");
case 3: strcpy(wday, "Thu");
case 4: strcpy(wday, "Fri");
case 5: strcpy(wday, "Sat");
case 6: strcpy(wday, "Sun");
}
switch(info->tm_mon){
case 0: strcpy(mon, "Jan");
case 1: strcpy(mon, "Feb");
case 2: strcpy(mon, "Mar");
case 3: strcpy(mon, "Apr");
case 4: strcpy(mon, "May");
case 5: strcpy(mon, "Jun");
case 6: strcpy(mon, "Jul");
case 7: strcpy(mon, "Aug");
case 8: strcpy(mon, "Sep");
case 9: strcpy(mon, "Oct");
case 10: strcpy(mon, "Nov");
case 11: strcpy(mon, "Dec");
}
char temp[5];
strcat(date, wday);
strcat(date, ", ");
sprintf(temp, "%2d", info->tm_mday);
strcat(date, temp);
strcat(date, " ");
strcat(date, mon);
sprintf(temp, " %4d ", (info->tm_year + 1900));
strcat(date, temp);
sprintf(temp, "%d:", info->tm_hour);
strcat(date, temp);
sprintf(temp, "%.2d:", info->tm_min);
strcat(date, temp);
sprintf(temp, "%.2d", info->tm_sec);
strcat(date, temp);
strcat(date, " UTC\n");
return date;
}
int sendall(int send_socket, char *buf, int *len)
{
int total = 0;
int bytesleft = *len;
int n;
while(total < *len)
{
n = send(send_socket, (buf + total), bytesleft, 0);
if(n == -1)
break;
total += n;
bytesleft -= n;
}
*len = total;
if(n==-1)
return -1;
else
return 0;
}
int sendfile(FILE* fp, int clntSock)
{
while(1)
{
unsigned char buff[256]={0};
int nread = fread(buff, 1, 256, fp);
if(nread > 0)
write(clntSock, buff, nread);
if(nread < 256)
{
if(feof(fp))
break; //eof
if(ferror(fp))
return -1;
}
}
return 0;
}
int parseSrc(char src[])
{
printf("%s", src);
if(src[0] == '/')
{
printf("SLASH");
src++;
return 2;
}
printf("%s", src);
return 1;
}
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen)
{
switch(sa->sa_family)
{
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
return s;
}
I am really stuck. Any help would be greatly appreciated!