-
什么是 socket?
socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
我们把插头插到插座上就能从电网获得电力供应,同样,为了与远程计算机进行数据传输,需要连接到因特网,而 socket 就是用来连接到因特网的工具。
socket 的典型应用就是 Web 服务器和浏览器:浏览器获取用户输入的 URL,向服务器发起请求,服务器分析接收到的 URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字、图片、视频等元素呈现给用户。
学习 socket,也就是学习计算机之间如何通信,并编写出实用的程序。 -
UNIX/Linux 中的 socket 是什么?
在 UNIX/Linux 系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作。
你也许听很多高手说过,UNIX/Linux 中的一切都是文件!那个家伙说的没错。
为了表示和区分已经打开的文件,UNIX/Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。例如:- 通常用 0 来表示标准输入文件(stdin),它对应的硬件设备就是键盘;
- 通常用 1 来表示标准输出文件(stdout),它对应的硬件设备就是显示器。
UNIX/Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。
请注意,网络连接也是一个文件,它也有文件描述符!
我们可以通过 socket() 函数来创建一个网络连接,或者说打开一个网络文件,socket() 的返回值就是文件描述符。有了文件描述符,我们就可以使用普通的文件操作函数来传输数据了,例如:- 用 read() 读取从远程计算机传来的数据;
- 用 write() 向远程计算机写入数据。
只要用 socket() 创建了连接,剩下的就是文件操作了,网络编程原来就是如此简单! -
SOCKET常见函数

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
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 }
5.服务端代码
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 }
6.最终截图:


来源:https://www.cnblogs.com/wyy165/p/12026037.html
