socket编程之客户--服务器通信程序学习
来源:互联网 发布:英雄联盟mac版美服 编辑:程序博客网 时间:2024/06/11 10:55
操作系统有五大功能,简单总结为:
操作系统的五大功能:1、进程管理2、内存管理3、文件系统4、网络管理5、设备管理
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
一、UNIX网络编程
在socket编程中会遇到很多函数,比如socket()、bind()、listen()等等,我会边学边记录熟悉这些函数的用法,简略的概述都在注释里,方便以后翻阅和学习
二、服务器端
#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 1024int main(){ int server_sockfd = socket(AF_INET,SOCK_STREAM, 0); //定义服务器端socket函数 ///定义sockaddr_in struct 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);//需要监听的端口,这里选择ANY表示所有网络端口都监听/*http://blog.csdn.net/yaxiya/article/details/6722083htonl就是把本机字节顺序转化为网络字节顺序h---host 本地主机to 就是to 了n ---net 网络的意思l 是 unsigned long同理可得ntohl就是网络字节序转化为本机字节序htonl和ntohl主要是为了防止在不同平台的机器数据存放格式不同http://bbs.csdn.net/topics/80351112 论坛讨论ntohl和htonl*/ /* bind,成功返回0,出错返回-1 int bind(int sockfd,const struct sockaddr* myaddr,socklen_t addrlen) 当socket函数返回一个描述符时,只是存在于其协议族的空间中,并没有分配一个具体的协议地址(这里指IPv4/IPv6和端口号的组合), bind函数可以将一组固定的地址绑定到sockfd上。其中:sockfd是socket函数返回的描述符;myaddr指定了想要绑定的IP和端口号,均要使用网络字节序-即大端模式;addrlen是前面struct sockaddr(与sockaddr_in等价)的长度。 */ if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } /*listen,成功返回0,出错返回-1int listen(int sockfd, int backlog);开始监听套接字sockfd:套接字,成功返回后进入监听模式,当有新连接并accept后会再建立一个套接字保存新的连接; backlog:暂且翻译为后备连接吧!下面详细介绍此参数: 1) 当TCP接收一个连接后(三次握手通过)会将此连接存在连接请求队列里面,并对队列个数+1,而backlog为此队列允许的最大个数,超过此值,则直接将新的连接删除,即不在接收新的连接。将这些处于请求队列里面的连接暂记为后备连接,这些都在底层自动完成,底层将连接添加到队列后等待上层来处理(一般是调用accept函数接收连接); 2) 当上层调用accept函数接收一个连接(处于请求队列里面的后备连接),队列个数会-1; 3) 那么这样一个加一个减,只要底层提交的速度小于上层接收的速度(一般是这样),很明显backlog就不能限制连接的个数,只能限制后备连接的个数。那为啥要用这个backlog呢?主要用于并发处理,当上层没来的及接收时,底层可以提交多个连接; 4) backlog的取值范围 ,一般为0-5。 http://www.cnblogs.com/mddblog/p/4492784.html */ if(listen(server_sockfd,QUEUE) == -1) //开始监听 { perror("listen"); exit(1); } ///客户端套接字 char buffer[BUFFER_SIZE]; struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); /*成功返回非负描述字,出错返回-1 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 开始等待客户端连过来套接字addr 和 addrlen 一般是NULL, 否则只允许addr指定的客户端连过来。 */ int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length); if(conn<0) { perror("connect"); exit(1); } while(1) { memset(buffer,0,sizeof(buffer));//清空buffer int len = recv(conn, buffer, sizeof(buffer),0);//recv函数返回其实际copy的字节数,http://blog.csdn.net/tiandyoin/article/details/30044781 if(strcmp(buffer,"exit\n")==0) break; fputs(buffer, stdout);//把接收到的内容输出到屏幕上 send(conn, buffer, len, 0); } close(conn); close(server_sockfd); return 0;}
三、客户端
#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(){ int sock_cli = socket(AF_INET,SOCK_STREAM, 0);//定义socket客户端函数/* int socket(int domain, int type, int protocol);创建socket, 返回文件描述符domain: AF_INET、 AF_INET6、 AF_UNIX、 AF_UPSPEC 指明了协议族/域比如AF_INET就是协议版本4,AF_INET6就是协议版本6type: SOCK_DGRAM、 SOCK_RAW、 SOCK_SEQPACKET、 SOCK_STREAM type是套接口类型SOCK_STREAM 提供有序的、可靠的、双向的和基于连接的字节流,使用带外数据传送机制,为Internet地址族使用TCP。SOCK_DGRAM 支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务,为Internet地址族使用UDP。protocol: IPPROTO_IP、 IPPROTO_IPV6、 IPPROTO_ICMP、 IPPROTO_RAW、IPPROTO_TCP、 IPPROTO_UDP protocol:套接口所用的协议。如调用者不想指定,可用0指定,表示缺省 */ //定义sockaddr_in结构体 http://blog.csdn.net/renchunlin66/article/details/52351751 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); //memset函数在驱动里见到过,清空某一段空间 servaddr.sin_family = AF_INET; //sin_family指代协议族,在socket编程中只能是AF_INET servaddr.sin_port = htons(MYPORT); //服务器端口,避免冲突建议设置大一些,因为比较小的端口都是默认的 servaddr.sin_addr.s_addr = inet_addr("192.168.216.128"); //服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); }/*int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);连接指定的服务器, 其中addr指定连接服务器的IP和端口*/ char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE];/*send类似于write int send(IN SOCKET s, IN const char FAR * buf, IN int len, IN int flags) 失败时返回 -1/SOCKET_ERROR其中: sockfd:发送端套接字描述符(非监听描述符) buf:应用要发送数据的缓存 len:实际要发送的数据长度 flag:一般设置为0 recv类似于read ssize_t recv(int sockfd,void *buf, size_t len,int flags)其中:sockfd:接收端套接字描述符;buf:指定缓冲区地址,用于存储接收数据;len:指定的用于接收数据的缓冲区长度;flags:一般指定为0其实在一般情况下可以互换,便于理解也可使用read和write */ while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)//fgets函数在之前获取IP的时候用到过,相当于检测是否clint有写入吧。 { send(sock_cli, sendbuf, strlen(sendbuf),0); //客户端发送 if(strcmp(sendbuf,"exit\n")==0)//在蜂鸣器中有用到strcmp,用来比较两个字符串,若完全相同则返回0 break; recv(sock_cli, recvbuf, sizeof(recvbuf),0); //接收 fputs(recvbuf, stdout);//fputs函数向指定的文件指针中写入字符串,这里是向屏幕中输出接收到的信息 /*stdout(Standardoutput)标准输出stdin(Standardinput)标准输入stderr(Standarderror)标准错误 */ memset(sendbuf, 0, sizeof(sendbuf));//清空使用的空间 memset(recvbuf, 0, sizeof(recvbuf)); } close(sock_cli);//关闭socket return 0;}
四、客户–服务器通信
服务器端接收:
客户端发送:
要先打开服务器端,然后再打开客户端连接
//http://blog.csdn.net/g_brightboy/article/details/12854117常用socket函数
阅读全文
0 0
- socket编程之客户--服务器通信程序学习
- socket编程之udp客户服务器
- socket之TCP多线程客户服务器编程
- 一个简单的客户-服务器的Socket通信程序
- socket编程(TCP单进程客户服务器通信)
- linux网络编程之socket(三):最简单的回射客户/服务器程序
- linux网络编程之socket:最简单的回射客户/服务器程序、time_wait 状态
- socket通信之四:多线程版本的客户/服务器模型
- socket通信之五:select多路复用的客户/服务器模型
- 【Unix 网络编程】TCP 客户/服务器简单 Socket 程序
- 【Unix 网络编程】UDP 客户/服务器简单 Socket 程序
- socket编程之TCP单进程客户服务器
- socket之tcp多进程客户服务器编程
- Socket 客户-服务器一对一通信(一)
- java网络编程学习之用java编写客户/服务器程序
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- linux网络编程之socket(三):最简单的回射客户/服务器程序、time_wait 状态
- 创建守护进程为什么要fork两次
- Linux--增加用户、添加用户组
- Idea环境下使用JFinal开发Web项目入门详解(图文版)
- 欧拉函数-欧拉定理-费马小定理
- 给android开发人员的十个建议
- socket编程之客户--服务器通信程序学习
- Android开发FlexboxLayout布局,你不在学就out了
- SVN 出现 database disk image is malformed
- 表单提交
- JavaScript的console.log用法
- DownloadManager+NumberProgressBar+Executors线程池实现多并发下载APK安装
- Node.JS Express入门
- <merge>标签使用
- git图形化工具GitKraken的使用——分支管理策略