简体   繁体   中英

TCP-Socket Programming in C

I have two files: tcp-demo-client.c and tcp-demo-server.c

Functionality: If the connection succeeds, the client receives a simple timestamp from the server. I like to modify the code that the server only sends the timestamp if the client hits the space key. How can I do that?

(It's my first socket project)

tcp-demo-client.c:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

int main(int argc, char **argv)
{
    int ret;                // return value from functions

    // Check command line arguments
    if (argc != 3) {
            fprintf(stderr,
                    "Missing parameters. Usage: %s <server-name-or-ip> <server-port>\n",
                    argv[0]);
            return 1;
    }
    // Address information structure
    struct addrinfo aii;
    // Set whole structure to 0s
    memset(&aii, 0, sizeof(aii));
    // A stream (TCP) connection
    aii.ai_socktype = SOCK_STREAM;
    // We do not care whether it is IPv4 or IPv6
    aii.ai_family = PF_UNSPEC;

    struct addrinfo *aio;
    // Get address information. 
    // First parameter is host string, either hostname or numerical IPv4/IPv6 address
    // Second parameter is port/service string, either as port number 
    // or well-known identifier, e.g. http
    // So, e.g. getaddrinfo( "www.compeng.uni-frankfurt.de", "http", ... getaddrinfo( "141.2.248.1", "80", ...
    // Third parameter is input address info structure (cf. above)
    // Fourth parameter is output address info structure, a linked list of potential addresses
    ret = getaddrinfo(argv[1], argv[2], &aii, &aio);
    if (ret) {
            fprintf(stderr, "Error getting address for %s:%s: %s\n",
                    argv[1], argv[2], gai_strerror(ret));
            return 1;
    }

    // File descriptor for the socket
    int sock = -1;
    struct addrinfo *iter;
    // Iterate over linked list of specified output addresses, 
    // use first address to which a connection can be established
    for (iter = aio; iter != NULL && sock == -1; iter = iter->ai_next) {
            // Create socket given the parameters from the found address info.
            sock =
                socket(iter->ai_family, iter->ai_socktype,
                       iter->ai_protocol);
            if (sock < 0)
                    continue;       // Appropriate socket could not be created, try next address

            // Socket created successfully, now try to connect to remote target address
            // taken from address info
            ret = connect(sock, iter->ai_addr, iter->ai_addrlen);
            if (ret) {
                    // Socket could not be connected to remote target
                    close(sock);    // Close socket
                    sock = -1;
                    continue;       // try next address
            }
    }
    freeaddrinfo(aio);      // Release address information allocated in getaddrinfo

    if (sock == -1) {
            // No connection at all could be established to remote target
            fprintf(stderr, "Unable to establish any connection to %s:%s\n",
                    argv[1], argv[2]);
            return 1;
    }


    // Maximum size of incoming message
    int msglen = 100;

    // Buffer for message
    char buf[msglen + 1];   // One more to ensure that there is a trailing NULL char.
    memset(buf, 0, msglen + 1);

    ret = read(sock, buf, msglen);     // Return value is amount of bytes read, -1 in case of error
    printf("Data read: '%s'\n", buf);

    // Clean up after us and close the socket.
    close(sock);
    return 0;
}

tcp-demo-server.c:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

#define MAXPENDING 5

int main(int argc, char **argv)
{
    unsigned short listen_port;     // Server port */
    int listen_sock;        // Socket descriptor for server
    int client_sock;        // Socket descriptor for client
    struct sockaddr_in listen_addr; // Local address */
    struct sockaddr_in client_addr; // Client address */

    // Check command line arguments
    if (argc != 2) {
            fprintf(stderr, "Missing parameters. Usage: %s <server-port>\n",
                    argv[0]);
            return 1;
    }
    // Create socket for incoming connections
    if ((listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
            perror("socket() failed");
            return 1;
    }
    // Construct local address structure 
    listen_port = atoi(argv[1]);    // First arg: listening port number

    memset(&listen_addr, 0, sizeof(listen_addr));   // Zero out structure
    listen_addr.sin_family = AF_INET;       // Internet address family
    listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);        // Any incoming interface
    listen_addr.sin_port = htons(listen_port);      // Local port

    // Bind to the local address
    if (bind
        (listen_sock, (struct sockaddr *)&listen_addr,
         sizeof(listen_addr)) < 0) {
            perror("bind() failed");
            return 1;
    }
    // Mark the socket so it will listen for incoming connections
    if (listen(listen_sock, MAXPENDING) < 0) {
            perror("listen() failed");
            return 1;
    }

    for (;;) {              /* Run forever */
            socklen_t addr_len = sizeof(client_addr);

            // Wait for a client to connect */
            if ((client_sock =
                 accept(listen_sock, (struct sockaddr *)&client_addr,
                        &addr_len)) < 0) {
                    perror("accept() failed");
                    return 1;
            }
            // client_sock is connected to a client
            printf("New connection from %s\n",
                   inet_ntoa(client_addr.sin_addr));

            // Create message to send
            time_t t = time(NULL);
            char *msg = ctime(&t);
            int msglen = strlen(msg) + 1;
            int ret;




            // Write the whole message in one go, fail if this does not work
            ret = write(client_sock, msg, msglen);
            // Return value is amount of bytes written, -1 in case of error
            if (ret != msglen) {
                    perror("Error during write");
                    return 1;
            }

            close(client_sock);
    }
    /* NOT REACHED */
    return 1;
}

I presume you mean you want the space char as unbuffered input. For POSIX, you could use something along the lines of this to capture the keypress:

#include <termios.h>

[...]

struct termios t;
int c, r;

[...]

tcgetattr(0, &t);
t.c_lflag &= ~(ICANON | ECHO);
t.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &t);

c = getchar();

r = send(sock, c, 1, 0);

Have a look at this for additional information:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM