簡體   English   中英

C語言聊天程序

[英]Chat Program in C

首先,這是家庭作業,因此請不要直接回答。 我正在用C語言編寫一個來回聊天程序。我對C語言非常陌生(剛剛開始學習此課程)。 目前,我有三個文件:

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>  
#include <strings.h>
#include <string.h> 
#include "chat.h"

#define SERVER_PORT 1725
#define MAX_PENDING 5
#define MAX_LINE 256

int main()
{
    struct sockaddr_in sin;
    char buf[MAX_LINE];
    int len;
    int s, new_s;
    struct chat_packet packet;

    /* build address data structure */
    bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(SERVER_PORT);

    /* setup passive open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) 
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) 
    {
        perror("simplex-talk: bind");
        exit(1);
    }
    listen(s, MAX_PENDING);

    /* wait for connection, then receive and print text */
    while(1) 
    {
        if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) 
        {
            perror("simplex-talk: accept");
            exit(1);
        }   

        /* Stay in the following loop until CTRL+C */
        while (len = recv(new_s, &packet, sizeof(packet), 0)) 
        {
            fputs(packet.sender_name, stdout);
            fputs(": ", stdout);
            fputs(packet.data, stdout); 
            fputs("\nYou: ", stdout);

            while (fgets(buf, sizeof(buf), stdin)) 
            {
                if(strlen(buf) > 144)
                {
                    printf("Your message is too long. Please enter a new message.\n");
                    continue;                                   
                }

                else
                {
                    buf[MAX_LINE-1] = '\0';

                    strncpy(packet.data,buf,144);
                    char sender[8] = "Mason"; /*should be argv[index of name]*/
                    strncpy(packet.sender_name, sender, 8);

                    send(new_s, &packet, sizeof(packet),0);
                }
            }
        }

        close(new_s);
    }
}

client.c

#include <stdio.h>
#include <stdlib.h> 
#include <strings.h> 
#include <string.h> 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "chat.h"

#define SERVER_PORT 1725
#define MAX_LINE 256

int main(int argc, char * argv[])
{
    FILE *fp;
    struct hostent *hp;
    struct sockaddr_in sin;
    char *host;
    char buf[MAX_LINE];
    int s;
    int len;
    struct chat_packet packet;

    if (argc==2) 
    {
        host = argv[1];
    }
    else 
    {
        fprintf(stderr, "usage: simplex-talk host\n");
        exit(1);
    }

    /* translate host name into peer's IP address */
    hp = gethostbyname(host);
    if (!hp) {
        fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
        exit(1);
    }
    /* build address data structure */
    bzero((char *)&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
    sin.sin_port = htons(SERVER_PORT);
    /* active open */
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) 
    {
        perror("simplex-talk: socket");
        exit(1);
    }
    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) 
    {
        perror("simplex-talk: connect");
        close(s);
        exit(1);
    }
    /* main loop: get and send lines of text */
    while (fgets(buf, sizeof(buf), stdin)) 
    {
        if(strlen(buf) > 144)
        {
            printf("Your message is too long. Please enter a new message.\n");
            continue;                                   /*This allows the user to re-enter a message post-error*/
        }
        else
        {
            buf[MAX_LINE-1] = '\0';

            strncpy(packet.data, buf, 144);
            char sender[8] = "Abby"; /*should be argv[index of name]*/
            strncpy(packet.sender_name, sender, 8);

            send(s, &packet, sizeof(packet), 0);    
            recv(s, &packet, sizeof(packet),0); 

            fputs(packet.sender_name, stdout);
            fputs(": ", stdout);
            fputs(packet.data, stdout);
            fputs("\nYou: ", stdout);
        }
    }
}

chat.h

#include <stdint.h> /* Needed for unsigned types */

#define MAX_DATA_LEN 144 /* So we are on 16-bit boundary */
#define USER_NAME_LEN 8

/* You must send this packet across the socket.  Notice there are
 * no pointers inside this packet. Why?*/
struct chat_packet {
    u_short version; /* 16 bits -- Set to version 2 in code */
    char sender_name[8]; /* 64 bits */
    char data[MAX_DATA_LEN]; /* Message goes in here */
};

我的講師給我循環時,除了客戶端和服務器中的所有內容外。 分配的基礎部分是往返聊天功能。 我正在使用命令行在PuTTY中運行所有內容。 我復制會話,在一個中運行客戶端,在另一個中運行服務器。 跑步:

./client serverName

。/服務器

我能夠來回走一次,然后沒有其他東西發送或接收。 我仍然可以打字,但是兩個會話在第一次來回之間無法看到彼此的消息。 我不確定我的代碼在哪里錯誤。 任何建議都將不勝感激,因為我是該語言的新手。 提前致謝!

好的,這是我的提示:考慮一下recv()零個字符時會發生什么。 另外,檢查服務器調用accept()與客戶端調用connect()時會發生什么。

您可能還想更明智地檢查recv()調用的返回值。 (為此,還有send() ;如果調用可能失敗,請檢查其返回值!)這是man recv頁面上的提示:

RETURN VALUES
     These calls return the number of bytes received, or -1 if an error occurred.

另外,如果您對調試器(例如gdb )不熟悉,我建議您學習它。 一時之間,您可能會考慮在代碼中添加printf()語句,以了解正在發生的情況。

另外,考慮一下您的“阻塞呼叫”在哪里。 如果您不熟悉“阻塞調用”的含義,則在您調用函數時將其稱為“阻塞”,並且該函數不會返回(“阻塞”),直到發生某些指定的事情為止。 例如,您的accept()將阻塞,直到接受連接為止。 您的fgets()將阻塞,直到收到一行文本為止。 如果您已經發送了太多數據,並且緩沖區已滿,則send()將阻塞。 recv()將阻塞,直到您收到指定的字節數為止。 recv()還具有您可能無法預期的行為,您可能需要考慮以下原因:

 If no messages are available at the socket, the receive call waits for a
 message to arrive, unless the socket is nonblocking (see fcntl(2)) in
 which case the value -1 is returned and the external variable errno set
 to EAGAIN.  The receive calls normally return any data available, up to
 the requested amount, rather than waiting for receipt of the full amount
 requested; this behavior is affected by the socket-level options
 SO_RCVLOWAT and SO_RCVTIMEO described in getsockopt(2).

在您的情況下,您的數據包可能足夠小,以至於您不會遇到必須自己重新組裝它們的情況。 但是檢查不會有什么壞處。

我認為這為您提供了探索的途徑...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM