https://www.write-bug.com/article/1274.html
一 需求分析
柏克莱套接字,又称为BSD 套接字是一种应用程序接口,用于网际插座与Unix域套接字,包括了一个用C语言写成的应用程序开发库,主要用于实现进程间通讯,在计算机网络通讯方面被广泛使用。
使用Berkeley套接字的系统有很多,本系统是在Ubuntu下用C语言进行socket编程。
二 程序设计
2.1 系统流程设计
如下图所示:

2.2 数据结构设计
socket编程问题中涉及的数据结构包括 套接口地址结等。
为了实现这些数据结构,用C语言定义变量如下:
structsockaddr_in {sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;};
三 程序实现
3.1 TCP通信流程
如下图所示:

3.2 实现技术
为实现上述设计,采用C语言,gcc4.9.2 + Vim开发环境。具体采用的技术如下:
socket()函数 int socket(int domain, int type, int protocol);
bind()函数 intbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
listen()函数 int listen(int sockfd, int backlog);
connect()函数 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
accept()函数 int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);
close()函数 int close(int fd);
实现步骤如下:
gcc -o server server.c
gcc -o client client.c
./server
./client
3.3 关键代码说明
为了进一步了解操作系统内核,学习了Linux操作系统的进程同步程序,主要程序源代码如下:
-----------------------client.c---------------------#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/shm.h>#define MYPORT 8887#define BUFFER_SIZE 1024int main() {///定义sockfdint sock_cli = socket(AF_INET,SOCK_STREAM, 0);///定义sockaddr_instruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(MYPORT); ///服务器端口servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip///连接服务器,成功返回0,错误返回-1if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("connect");exit(1);}char sendbuf[BUFFER_SIZE];char recvbuf[BUFFER_SIZE];memset(recvbuf, '\0', sizeof(recvbuf));while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送if(strcmp(sendbuf,"q\n")==0)break;recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收fputs(recvbuf, stdout);memset(sendbuf, 0, sizeof(sendbuf));memset(recvbuf, 0, sizeof(recvbuf));}close(sock_cli);return 0;}-----------------------server.c-----------------------#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/shm.h>#define MYPORT 8887#define QUEUE 20#define BUFFER_SIZE 1024char ans[BUFFER_SIZE];void _itoa(int n) {char ans2[BUFFER_SIZE];int l = 0;while (n) {ans2[l++] = n % 10 + '0';n /= 10;}int l2 = 0;while (l) {ans[l2++] = ans2[--l];}ans[l2++] = '\n';ans[l2] = '\0';}int main() {///定义sockfdint server_sockfd = socket(AF_INET,SOCK_STREAM, 0);///定义sockaddr_instruct sockaddr_in server_sockaddr;server_sockaddr.sin_family = AF_INET;server_sockaddr.sin_port = htons(MYPORT);server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);///bind,成功返回0,出错返回-1if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1) {perror("bind");exit(1);}///listen,成功返回0,出错返回-1if(listen(server_sockfd,QUEUE) == -1) {perror("listen");exit(1);}///客户端套接字char buffer[BUFFER_SIZE];struct sockaddr_in client_addr;socklen_t length = sizeof(client_addr);///成功返回非负描述字,出错返回-1int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);if(conn<0) {perror("connect");exit(1);}while(1) {memset(buffer,0,sizeof(buffer));int len = recv(conn, buffer, sizeof(buffer),0);if(strcmp(buffer,"q\n")==0)break;int a = 0;int i, blen = strlen(buffer);for (i = 2; i < blen - 1; i++) {if (buffer[i] != ',') {a = a * 10 + buffer[i] - '0';} else {i++;break;}}int b = 0;for (; i < blen - 1; i++) {b = b * 10 + buffer[i] - '0';}_itoa(a+b);fputs(buffer, stdout);send(conn, ans, strlen(ans), 0);}close(conn);close(server_sockfd);return 0;}
这一段程序的主要功能为:
向server发送要计算的表达式并接收计算结果
接收client发送的表达式并计算,在终端输出表达式并把计算结果发回到client
四 运行测试
例如,客户端输入+,100,200,根据分析,运行结果应为:300
实际运行结果如下:

本文介绍了一种基于C语言的Socket编程方法,通过TCP通信实现了客户端与服务器间的表达式计算交互。主要内容包括需求分析、程序设计、实现技术及关键代码说明。

被折叠的 条评论
为什么被折叠?



