C 中的 TCP 客户端和服务器

TCP Client and Servers in C

我在 C 中创建了一个 TCP 客户端和一个服务器,并在两个终端中执行。但是在更改和编译代码后,我无法获得输出。服务器和客户端都保留 运行 并且不打印任何内容。

这是我的服务器代码

/* Sample TCP server */
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>

int fsize(FILE *fp){
    int prev=ftell(fp);
    fseek(fp, 0L, SEEK_END);
    int sz=ftell(fp);
    fseek(fp,prev,SEEK_SET); //go back to where we were
    return sz;
}

int main(int argc, char**argv)
{
int listenfd,connfd,n, length;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
char* banner = "ack";
char buffer[1000];

/* one socket is dedicated to listening */
listenfd=socket(AF_INET,SOCK_STREAM,0);

/* initialize a sockaddr_in struct with our own address information for binding the socket */
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);

/* binding */
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
listen(listenfd,0);
clilen=sizeof(cliaddr);

while(1){

    /* accept the client with a different socket. */
    connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
    // the uninitialized cliaddr variable is filled in with the
    n = recvfrom(connfd,buffer,1000,0,(struct sockaddr *)&cliaddr,&clilen);//information of the client by recvfrom function
    buffer[n] = 0;
    sendto(connfd,banner,strlen(banner),0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
    printf("Received:%s\n",buffer);

    FILE *fp = fopen("serverfile.txt", "r");
    length = fsize(fp);
    printf("%d\n", length);

}



return 0;
}

这是我的客户端代码

/* Sample TCP client */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)

{
    int sockfd,n;
    struct sockaddr_in servaddr;
    char banner[] = "Hello TCP server! This is TCP client";
    char buffer[1000];
    if (argc != 2)
    {
        printf("usage: ./%s <IP address>\n",argv[0]);
        return -1;
    }
    /* socket to connect */s
    sockfd=socket(AF_INET,SOCK_STREAM,0);

    /* IP address information of the server to connect to */
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=inet_addr(argv[1]);
    servaddr.sin_port=htons(32000);
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    sendto(sockfd,banner,strlen(banner),0, (struct sockaddr*)&servaddr,sizeof(servaddr));
    n=recvfrom(sockfd,buffer,10000,0,NULL,NULL);
    buffer[n]=0; 
    printf("Received:%s\n",buffer);
    return 0;
}

您的主要问题是您没有检查套接字上的任何操作的结果,因此服务器或客户端完全有可能报告一条错误消息,使您的问题的答案显而易见。

特别是,如果服务器无法绑定或侦听侦听套接字,它将进入无限循环,使失败的接受、读取和写入永远失败。

我怀疑,重启服务器的时候,之前的socket还处于TIME_WAIT状态,所以绑定不了端口。您可以在创建套接字后使用以下命令来解决此问题:

int reuseaddr = 1;
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr))==-1) 
{
    fprintf(stderr, "%s",strerror(errno));
    exit(1);
}

请注意上面如何检查 return 结果并在失败时报告错误。您需要在每次调用 socket()listen()bind()connect()recvfrom()sendto() 和 [=17 后执行此操作或类似操作=].

请注意,我是如何将 close() 放入该列表中的。当你完成它时,你真的必须在连接套接字上调用它,特别是在服务器上,否则你会在 connfd.

中泄漏文件描述符