基于C/S架构的SOCKET C的网络hello程序

  1. 什么是SOCKET?

  在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据

  SOCKET起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现:即socket是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。Socket()函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。



  图中可以看到socket是位于应用层和传输层之间的一个抽象层,那么它存在的意义又是什么呢?其实没有socket抽象层,也是可以的,但是,当我们使用不同的协议进行通信时就得使用不同的接口,还得处理不同协议的各种细节,这就增加了开发的难度,软件也不易于扩展。于是UNIX BSD就发明了socket这种东西,socket屏蔽了各个协议的通信细节,使得程序员无需关注协议本身,直接使用socket提供的接口来进行互联的不同主机间的进程的通信。这就好比操作系统给我们提供了使用底层硬件功能的系统调用,通过系统调用我们可以方便的使用磁盘(文件操作),使用内存,而无需自己去进行磁盘读写,内存管理。socket其实也是一样的东西,就是提供了tcp/ip协议的抽象,对外提供了一套接口,同过这个接口就可以统一、方便的使用tcp/ip协议的功能了。
 

2.Linux SOCKET套接字函数

  在了解了SOCKET基本原理之后,我们来看看实际编程中的那些SOCKET函数,SOCKET客户端和服务器端调用的函数如下同所示。


    

  3.客户端代码:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<errno.h>
 5 #include<sys/types.h>
 6 #include<sys/socket.h>
 7 #include<netinet/in.h>
 8 
 9 #define MAXLINE 4096
10 
11 int main(int argc, char** argv)
12 {
13     int     sockfd, n;
14     char    recvline[4096], sendline[4096];
15     struct  sockaddr_in    servaddr;
16 
17     //命令行启动时输入服务器IP地址
18     if(argc != 2) {
19         printf("usage: ./client <ipaddress>\n");            
20         exit(0);
21     }
22 
23     //获取SOCKET描述符
24     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
25         printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
26         exit(0);
27     }
28 
29     memset(&servaddr, 0, sizeof(servaddr));
30     servaddr.sin_family = AF_INET;
31     servaddr.sin_port = htons(6666);
32     if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
33         printf("inet_pton error for %s\n",argv[1]);
34         exit(0);
35     }
36 
37     //与服务器连接
38     if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
39         printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
40         exit(0);
41     }
42 
43     //通过while循环可以一直向服务器发送数据
44     while (1) {
45         printf("send msg to server: \n");
46         scanf("%s", sendline);
47 
48         //将用户stdin输入的大写字符串发送给服务器
49         if(send(sockfd, sendline, strlen(sendline), 0) < 0) {
50             printf("client send msg error: %s(errno: %d)\n", strerror(errno), errno);
51             exit(0);
52         }
53 
54         //若发送"quit"则退出客户端程序
55         if (strcmp(sendline, "quit") == 0){
56             printf ("close");
57             break;
58         }
59         int recvLength = 0;
60 
61         //接受经过服务器小写处理的字符串
62         recvLength = recv(sockfd, recvline, 200, 0);
63         printf("recv length = %d\n", recvLength);
64         recvline[recvLength] = '\0';
65         printf("recv lower msg from server: %s\n", recvline);
66     }
67     
68 
69     close(sockfd);
70 }

  4.服务器端代码:

  

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<errno.h>
 5 #include<sys/types.h>
 6 #include<sys/socket.h>
 7 #include<netinet/in.h>
 8 #include<ctype.h>
 9 
10 #define MAXLINE 4096
11 
12 int main(int argc, char** argv) 
13 {
14     int     listenfd, connfd;
15     struct  sockaddr_in servaddr;
16     char    recvbuff[4096], sendbuff[4096];
17     int     n;
18     
19     // 获取socket套接字
20     if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
21         printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
22         exit(0);
23     }
24 
25     //sockaddr结构体初始化,端口为6666
26     memset(&servaddr, 0, sizeof(servaddr));
27     servaddr.sin_family = AF_INET;
28     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
29     servaddr.sin_port = htons(6666);
30 
31     if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
32         printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
33         exit(0);
34     }
35 
36     //开始监听
37     if (listen(listenfd, 10)) {
38         printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
39         exit(0);
40     }
41 
42     //与客户端建立连接
43     printf("======waiting for client's request======\n");
44     if ((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1) {
45         printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
46     }
47 
48     //一直接受客户端发送的数据
49     while (1) {
50         
51         n = recv(connfd, recvbuff, MAXLINE, 0);
52         recvbuff[n] = '\0';
53         //对收到的字符串进行小写处理
54         for (int i = 0; i < strlen(recvbuff); i++) {
55             recvbuff[i] = tolower(recvbuff[i]);
56         }
57         //若收到“quit”字符串则退出
58         printf("recv msg from client: %s\n", recvbuff);
59         if (strcmp(recvbuff, "quit") == 0) {
60             printf("close");
61             break;
62         } 
63         //将处理完的字符串返回给客户端
64         printf("recv length  = %d\n\n", strlen(recvbuff));
65         if (send(connfd, recvbuff, strlen(recvbuff), 0) < 0) {
66             printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
67             exit(0);
68         }
69     }
70     close(connfd);
71     close(listenfd);
72 }

  5.实验截图;

  客户端:

  

  服务器端:

  

  

  

猜你喜欢

转载自www.cnblogs.com/n-p-2019-blogs/p/12025323.html
今日推荐