1 /* tcpServer.c 2 * 3 * Simple Winsock TCP server test. 4 * Later will be used as base for ReactOS telnetd 5 * 6 * HISTORY: 7 * 6-15-02 - Added Winsock support to UNIX tcp test 8 * 6-16-02 - Removed Unix support 9 * 6-17-02 - Added extra comments to code 10 * 11 */ 12 13 #include <winsock2.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <io.h> 17 18 #undef ERROR 19 #define SUCCESS 0 20 #define ERROR 1 21 22 #define END_LINE 0x0A 23 #define SERVER_PORT 23 24 #define MAX_MSG 100 25 26 /* function readline */ 27 int read_line(); 28 29 int main (int argc, char *argv[]) { 30 31 WORD wVersionRequested; 32 WSADATA WsaData; 33 INT Status; 34 int sd, newSd, cliLen; 35 36 struct sockaddr_in cliAddr, servAddr; 37 char line[MAX_MSG]; 38 39 wVersionRequested = MAKEWORD(2, 2); 40 41 Status = WSAStartup(wVersionRequested, &WsaData); 42 if (Status != 0) { 43 printf("Could not initialize winsock dll.\n"); 44 return FALSE; 45 } 46 47 /* create socket */ 48 sd = socket(AF_INET, SOCK_STREAM, 0); 49 if(sd<0) { 50 perror("cannot open socket "); 51 WSACleanup(); 52 return ERROR; 53 } 54 55 /* bind server port */ 56 servAddr.sin_family = AF_INET; 57 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 58 servAddr.sin_port = htons(SERVER_PORT); 59 60 if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) { 61 perror("cannot bind port "); 62 WSACleanup(); 63 return ERROR; 64 } 65 66 listen(sd,5); 67 68 while(1) { 69 70 printf("%s: \n" 71 "To start test, Please telnet to localhost (127.0.0.1) port 23 \n" 72 "When connected input raw data followed by End of Line\n" 73 "Test is now running on TCP port %u\n",argv[0],SERVER_PORT); 74 75 cliLen = sizeof(cliAddr); 76 newSd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen); 77 if(newSd<0) { 78 perror("cannot accept connection "); 79 WSACleanup(); 80 return ERROR; 81 } 82 83 /* init line */ 84 memset(line,0x0,MAX_MSG); 85 86 /* receive segments */ 87 while(read_line(newSd,line)!=ERROR) { 88 89 printf("%s: received from %s:TCP%d : %s\n", argv[0], 90 inet_ntoa(cliAddr.sin_addr), 91 ntohs(cliAddr.sin_port), line); 92 /* init line */ 93 memset(line,0x0,MAX_MSG); 94 95 } /* while(read_line) */ 96 97 } /* while (1) */ 98 99 } 100 101 102 /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ 103 /* this function is experimental.. I don't know yet if it works */ 104 /* correctly or not. Use Steven's readline() function to have */ 105 /* something robust. */ 106 /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ 107 108 /* rcv_line is my function readline(). Data is read from the socket when */ 109 /* needed, but not byte after bytes. All the received data is read. */ 110 /* This means only one call to recv(), instead of one call for */ 111 /* each received byte. */ 112 /* You can set END_CHAR to whatever means endofline for you. (0x0A is \n)*/ 113 /* read_lin returns the number of bytes returned in line_to_return */ 114 int read_line(int newSd, char *line_to_return) { 115 116 static int rcv_ptr=0; 117 static char rcv_msg[MAX_MSG]; 118 static int n; 119 int offset; 120 121 offset=0; 122 123 while(1) { 124 if(rcv_ptr==0) { 125 /* read data from socket */ 126 memset(rcv_msg,0x0,MAX_MSG); /* init buffer */ 127 n = recv(newSd, rcv_msg, MAX_MSG, 0); /* wait for data */ 128 if (n<0) { 129 perror(" cannot receive data "); 130 return ERROR; 131 } else if (n==0) { 132 printf(" connection closed by client\n"); 133 closesocket(newSd); 134 WSACleanup(); 135 return ERROR; 136 } 137 } 138 139 /* if new data read on socket */ 140 /* OR */ 141 /* if another line is still in buffer */ 142 143 /* copy line into 'line_to_return' */ 144 while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr<n) { 145 memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1); 146 offset++; 147 rcv_ptr++; 148 } 149 150 /* end of line + end of buffer => return line */ 151 if(rcv_ptr==n-1) { 152 /* set last byte to END_LINE */ 153 *(line_to_return+offset)=END_LINE; 154 rcv_ptr=0; 155 return ++offset; 156 } 157 158 /* end of line but still some data in buffer => return line */ 159 if(rcv_ptr <n-1) { 160 /* set last byte to END_LINE */ 161 *(line_to_return+offset)=END_LINE; 162 rcv_ptr++; 163 return ++offset; 164 } 165 166 /* end of buffer but line is not ended => */ 167 /* wait for more data to arrive on socket */ 168 if(rcv_ptr == n) { 169 rcv_ptr = 0; 170 } 171 172 } /* while */ 173 } 174 175 176