学科分类
目录
Linux编程

C/S模型-TCP

在创建socket时,若将socket()函数中的参数type设置为SOCK_STREAM,程序将采用TCP传输协议,先使通信双方建立连接,再以数据段的形式传输数据。

案例1:编写C/S模式的程序,分别创建服务器和客户端。客户端的功能是从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;服务器的功能是从客户端发来的字符,将每个字符转换为大写再返回给客户端。案例实现如下。

tcpserver.c //服务器端程序

 1    #include <stdio.h>
 2    #include <stdlib.h>
 3    #include <string.h>
 4    #include <unistd.h>
 5    #include <sys/socket.h>
 6    #include <netinet/in.h>
 7    #include <arpa/inet.h>
 8    #define MAXLINE 80                            //最大连接数
 9    #define SERV_PORT 6666                        //服务器端口号
 10    int main(void)
 11    {
 12        struct sockaddr_in servaddr, cliaddr;     //定义服务器与客户端地址结构体
 13        socklen_t cliaddr_len;                     //客户端地址长度
 14        int listenfd, connfd;
 15        char buf[MAXLINE];
 16        char str[INET_ADDRSTRLEN];
 17        int i, n;
 18         //创建服务器端套接字文件
 19        listenfd = socket(AF_INET, SOCK_STREAM, 0);
 20         //初始化服务器端口地址
 21        bzero(&servaddr, sizeof(servaddr));    //将服务器端口地址清零
 22        servaddr.sin_family = AF_INET;
 23        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 24        servaddr.sin_port = htons(SERV_PORT);
 25         //将套接字文件与服务器端口地址绑定
 26        bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
 27         //监听,并设置最大连接数未20
 28        listen(listenfd, 20);
 29        printf("Accepting connections ...\n");
 30         //接收客户端数据,并处理请求
 31        while (1) {
 32            cliaddr_len = sizeof(cliaddr);
 33            connfd =accept(listenfd, (struct sockaddr *)&cliaddr,&cliaddr_len);
 34            n = recv(connfd, buf, MAXLINE,0);
 35            printf("received from %s at PORT %d\n",
 36            inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
 37            ntohs(cliaddr.sin_port));
 38            for (i = 0; i < n; i++)
 39                buf[i] = toupper(buf[i]);
 40            send(connfd, buf, n,0);
 41           //关闭连接
 42            close(connfd);
 43        }
 44        return 0;
 45    }

tcpclient.c 客户端程序

 1    #include <stdio.h>
 2    #include <stdlib.h>
 3    #include <string.h>
 4    #include <unistd.h>
 5    #include <sys/socket.h>
 6    #include <netinet/in.h>
 7    #define MAXLINE 80
 8    #define SERV_PORT 6666
 9    int main(int argc, char *argv[])
 10    {
 11        struct sockaddr_in servaddr;        //定义服务器地址结构体
 12        char buf[MAXLINE];
 13        int sockfd, n;
 14        char *str;
 15        if (argc != 2) {
 16            fputs("usage: ./client message\n", stderr);
 17            exit(1);
 18        } 
 19        str = argv[1];
 20         //创建客户端套接字文件
 21        sockfd = socket(AF_INET, SOCK_STREAM, 0);
 22         //初始化服务器端口地址
 23        bzero(&servaddr, sizeof(servaddr));
 24        servaddr.sin_family = AF_INET;
 25        inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
 26        servaddr.sin_port = htons(SERV_PORT);
 27         //请求链接
 28        connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
 29         //发送数据
 30        send(sockfd, str, strlen(str),0);
 31         //接收客户端返回的数据
 32        n = recv(sockfd, buf, MAXLINE,0);
 33        printf("Response from server:\n");
 34         //将客户端返回的数据打印到终端
 35        write(STDOUT_FILENO, buf, n);
 36         //关闭连接
 37        close(sockfd);
 38        return 0;
 39    }

编译以上两端代码,打开两个终端窗口,先执行服务器端程序,再执行客户端程序,同时输入需要转换的字符串,服务器端和客户端对应的终端中分别打印如下信息:

服务器端:

Accepting connections ...
received from 127.0.0.1 at PORT 41957
received from 127.0.0.1 at PORT 41958

客户机端:

[itheima@localhost ~]$ ./tcpclient hello
Response from server:
HELLO[itheima@localhost ~]$ ./tcpclient helloworld
Response from server:
HELLOWORLD[itheima@localhost ~]$

由程序执行结果可知,服务器成功将客户端发来的字符串转换成大写,案例实现成功。

点击此处
隐藏目录