socket编程之客户--服务器通信程序学习
2017-06-19 15:26
495 查看
操作系统有五大功能,简单总结为:
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
在socket编程中会遇到很多函数,比如socket()、bind()、listen()等等,我会边学边记录熟悉这些函数的用法,简略的概述都在注释里,方便以后翻阅和学习
客户端发送:
要先打开服务器端,然后再打开客户端连接
//http://blog.csdn.net/g_brightboy/article/details/12854117常用socket函数
操作系统的五大功能: 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 1024 int 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/6722083 htonl就是把本机字节顺序转化为网络字节顺序 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,出错返回-1 int 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(c 4000 onn); 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 1024 int 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就是协议版本6 type: 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函数
相关文章推荐
- 一个简单的客户-服务器的Socket通信程序
- Python网络编程之socket编程(一)--使用TCP和UDP客户端和服务器通信
- Linux socket编程学习初步(3)--客户端向服务器请求文件
- php socket简单的服务器通信程序
- socket之TCP多线程客户服务器编程
- Windows网络编程入门:简单的客户端和服务器通信程序调试
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
- Java_socket程序学习01-一个客户端对一个服务器
- Java_socket程序学习02-一个客户端对一个服务器-客户端键盘输入
- Java_socket程序学习03-一个客户端对一个服务器-交互(客户端)--02
- Linux C UDP Socket实现客户与服务器简单通信
- Linux下socket编程实现客户机服务器通信的例子
- Java网络编程学习笔记(六)服务器Socket
- Android中socket编程实现简单的客户端和服务器之间的通信
- 利用C#进行socket编程(模拟服务器和客户端通信)
- 粤嵌-Android学习之Socket编程 手机为服务器 模拟器为客户端
- Linux socket编程(二) 服务器与客户端的通信
- 基于UDP的socket客户服务器编程
- Linux socket编程-最简单的服务器和客户端程序