Linux-C语言 网络TCP单次通信、多次通信、多线程通信逐步实现

一、TCP通信,只发送一次就结束程序

功能描述:

1、服务端一次只能连接一个客户端。
2、客户端只能向服务端发送一次消息,消息返回后客户端和服务器程序结束。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。

步骤一:

依次编译客户端和服务器源程序,然后使用ifconfig命令查看虚拟机IP地址,用于之后客户端使用这个IP地址访问服务器。
在这里插入图片描述

步骤二:

打开两个终端,客户端服务器各一个,先运行服务器端,再运行客户端,全部运行之后便可以通过客户端向服务器发送消息了。
在这里插入图片描述

客户端源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>

#define SERVPORT 8080

int main(int argc,int *argv[])
{
    
    
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
    
    
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    while(fgets(sendline,100,stdin) != NULL)
    {
    
    
        sendto(sockfd,sendline,strlen(sendline),0,
               (struct sockaddr *)&servaddr,sizeof(servaddr));

        recv_len = recvfrom(sockfd,recvline,100,0,NULL,NULL);

        recvline[recv_len] = '\0';

        fputs(recvline,stdout);

    }

    close(sockfd);

    return 0;
}

服务器源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>

#define SERVPORT 8080

int main(int argc)
{
    
    
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully!\n");

    listen(listenfd,10);

    connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
    printf("connect sucessifully!\n");

    recv_len = recv(connfd,buff,100,0);

    buff[recv_len] = '\0';
    printf("received the following:\n");
    printf("%s",buff);

    for(int i=0; i<recv_len; i++)
    {
    
    
        buff[i] = toupper(buff[i]);
    }
    send_len = send(connfd,buff,recv_len,0);

    close(listenfd);
    return 0;
}

二、TCP通信,服务端与客户端实现多次通信

功能描述:

1、服务端一次只能连接一个客户端。
2、客户端可以向服务端多次发送消息,直到客户端发送一个空的消息后,客户端和服务器程序结束。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。

步骤同第一个(省)

客户端源码:

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<unistd.h>
#define SERVPORT 8080

int main(int argc,char *argv[])
{
    
    
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
    
    
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    printf("send to service  :  ");
    while(fgets(sendline,100,stdin) != NULL)
    {
    
    
        send(sockfd,sendline,strlen(sendline),0);

        recv_len = recv(sockfd,recvline,100,0);

        recvline[recv_len] = '\0';
        printf("back from service:  ");
        fputs(recvline,stdout);
        printf("------------------------------\n");
        printf("send to service  :  ");
        //close(sockfd);
        //break;
    }

    close(sockfd);

    return 0;
}

服务器源码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>

#define SERVPORT 8080

int main(int argc)
{
    
    
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully! \n");

    listen(listenfd,10);
    printf("Waiting for clients to connect...\n");
    connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
    printf("%d connect sucessifully!\n",connfd);

    while(1)
    {
    
    
        recv_len = recv(connfd,buff,100,0);
        if(recv_len == 0)
        {
    
    
            break;
        }
        buff[recv_len] = '\0';
        printf("received the following:\n");
        printf("%s",buff);

        for(int i=0; i<recv_len; i++)
        {
    
    
            buff[i] = toupper(buff[i]);
        }
        send_len = send(connfd,buff,recv_len,0);
    }

    close(listenfd);
    return 0;
}

三、多线程实现TCP-Socket通信

功能描述:

1、服务端可以同时连接多个客户端。
2、多个客户端并发运行,同时实现与服务器的通信。
3、客户端向服务端发送一个字符串,服务端将字符串改为大写后返还到客户端。
4、客户端全部关闭时,服务器仍然运行,当有新的客户端连接时,继续工作。

步骤一:

依次编译客户端和服务器源程序,然后使用ifconfig命令查看虚拟机IP地址,用于之后客户端使用这个IP地址访问服务器。
在这里插入图片描述

步骤二:

然后打开三个终端,一个为服务器,两个为客户端,
在这里插入图片描述

步骤三:

照着下图,先运行服务器,再运行客户端,全部运行之后便可以通过客户端向服务器发送消息了。
在这里插入图片描述

效果展示:

在这里插入图片描述

客户端源码:

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<unistd.h>

#define SERVPORT 8080

int main(int argc,char *argv[])
{
    
    
    int sockfd;
    int recv_len;
    struct sockaddr_in servaddr,cliaddr;
    char sendline[100];
    char recvline[100];

    if(argc != 2)
    {
    
    
        printf("need server address\n");
        exit(0);
    }

    sockfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    printf("send to service  :  ");
    while(fgets(sendline,100,stdin) != NULL)
    {
    
    
        send(sockfd,sendline,strlen(sendline),0);

        recv_len = recv(sockfd,recvline,100,0);

        recvline[recv_len] = '\0'; // 给接收到的结果加上字符串结束符
        printf("back from service:  ");
        fputs(recvline,stdout); //将收到的结果发送到控制台
        printf("------------------------------\n");
        printf("send to service  :  ");
        //close(sockfd);
        //break;
    }
    
    close(sockfd);
    return 0;
}

服务器源码

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>

#include<ctype.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<pthread.h>

#define SERVPORT 8080
#define CONNECTNUM 10
void thread_fun(void * cconnfd)
{
    
    
    int connfd =*(int *)cconnfd;
    int recv_len,send_len;
    char buff[100];
    
    while(1)
    {
    
    
        recv_len = recv(connfd,buff,100,0);
        if(recv_len == 0)
        {
    
    
            break;
        }
        buff[recv_len] = '\0';
        printf("received from client%d the following:\n",connfd);
        printf("%s",buff);


        for(int i=0; i<recv_len; i++)
        {
    
    
            buff[i] = toupper(buff[i]);
        }
        send_len = send(connfd,buff,recv_len,0);
        printf("have replied client%d ,over. \n ",connfd);
        printf("------------------------------ \n");
    }
    pthread_exit(NULL);
}
int main(int argc)
{
    
    
    int listenfd,connfd,recv_len,send_len;
    socklen_t clilen;
    struct sockaddr_in servaddr,cliaddr;
    char buff[100];
    pthread_t pid[CONNECTNUM];

    listenfd = socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
    printf("bind is sucessifully! \n");

    listen(listenfd,10);
    printf("Waiting for clients to connect...\n");

    for(int j =0; j<CONNECTNUM; j++)
    {
    
    
        connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
        printf("%d connect sucessifully!\n",connfd);
        pthread_create(&pid[j],NULL,(void *)thread_fun,&connfd);
    }

    close(listenfd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/quxuexi/article/details/125148518
今日推荐