使用套接字实现简单TCP服务器客户端模型
来源:互联网 发布:剑网3成男捏脸数据图表 编辑:程序博客网 时间:2024/06/06 05:11
利用套接字实现一个简单的TCP服务器客户端模型基本步骤如下:
1.创建套接字
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数描述:
domian:协议域,AF_INET 对应 ipv4,AF_INET6 对应 ipv6, AF_UNIX 表示这个socket是非网络形式的unix域,可以用来进行非网络形式的进程间通信。
type:指定socket类型
1.SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。 这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
2.SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
3.SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
返回值:
成功返回socket描述符,失败返回-1
2.将服务器IP与端口和套接字进行绑定
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数描述:
sockfd:通过socket()函数创建,用来表示唯一一个socket
addr:指向要绑定给sockfd的协议地址(协议类型,IP,端口号)
addrlen:对应地址长度
返回值:
成功返回0,失败返回-1
注意:
在IPv4因特网域AF_INET中,套接字地址用结构sockaddr_in表示,如下:
struct sockaddr_in
{
sa_family_t sin_family; //unsigned short 地址族
in_port_t sin_sport; //uint16_t
struct in_addr sin_addr; //IPv4
};
struct in_addr
{
in_addr_t s_addr; //uint32_t
};
3.监听请求
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
参数描述:
sockfd:要监听的套接字
backlog:连接队列长度
backlog 具体一些是什么意思呢?每一个连入请求都要进入一个连入请求队列,等待listen 的程序调用accept()函数来接受这个连接。当系统还没有调用accept()函数的时候,如果有很多连接,那么本地能够等待的最大数目就是backlog 的数值。
返回值:
成功返回0,失败返回-1
4.服务器端接受监听到的请求
当服务器端进行监听到一个连接请求时,就可以使用accept()函数来接受这个请求。
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数描述:
socket:服务器的套接字
addr:用于存储客户端的协议地址(协议类型,IP,端口号)
addrlen:地址长度(sizeof(addr))
返回值:
成功返回一个新的套接字描述符,代表与返回客户端的TCP连接
5.客户端连接服务器
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数描述:
sockfd:客户端的sockfd
addr:用于存储服务器的协议地址(协议类型,IP,端口号)
addrlen:地址长度(sizeof(addr))
返回值:
成功返回0,失败返回-1
注意:
在实现过程中还应注意网络字节序的问题,主机的字节序是不确定的,有的使用大端存储,有的使用小端存储,为了不使网络通信因为机器之间存储模式而造成错误,TCP/IP协议规定网络数据流使用大端字节序。
下面库函数可以完成主机序列和为网络序列的转换:
#include <arpa/inet.h>
//主机序列到网络序列
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
//网络序列到主机序列
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
server:#include<stdio.h>#include<string.h>#include<sys/socket.h>#include<netinet/in.h>#include<error.h>#include<unistd.h>#include<sys/types.h>static void Usage(char* proc){ printf("Usage: %s [local_ip] [local_port]\n", proc);}int startup(char* ip, int port){ //1.创建文件特性套接字 //AF_INET ipv4,SOCK_STREAM,基于字节流服务 int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { perror("socket"); return 2; } printf("sock = %d\n", sock); struct sockaddr_in local; //确定地址协议类型 local.sin_family = AF_INET; //绑定端口 local.sin_port = htons(port); //绑定ip //这里的IP是点分十进制,使用inet_addr()可以将其转换成二进制 local.sin_addr.s_addr = inet_addr(ip); //2.绑定网络特性将套接字与服务器ip和端口号绑定 if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) { perror("bind"); return 3; } //3.监听请求 if(listen(sock, 10) < 0) { perror("listen"); return 4; } return sock;}int main(int argc, char* argv[]){ if(argc != 3) { Usage(argv[0]); return 1; } //获取套接字 int listen_sock = startup(argv[1], atoi(argv[2])); while(1) { //用于存储连接的客户端地址信息(地址类型,IP,端口号) struct sockaddr_in client; socklen_t len = sizeof(client); //4.接受监听到的连接 int new_sock = accept(listen_sock,(struct sockaddr*)&client, &len); if(new_sock < 0) { perror("accept"); return 5; } while(1) { char buf[1024]; //从套接字读取信息到buf中 ssize_t s = read(new_sock, buf, sizeof(buf) - 1); if(s > 0) { buf[s] = 0; printf("client# %s\n", buf); printf("Please Enter# "); fflush(stdout); //从键盘输入信息到buf中 ssize_t _s = read(0, buf, sizeof(buf)-1); buf[_s-1] = 0; //发送信息到套接字 write(new_sock, buf, strlen(buf)); } else if(s == 0) { printf("client colse !!\n"); return 6; } else { perror("read"); return 7; } } } return 0;}
client:#include<stdio.h>#include<string.h>#include<sys/socket.h>#include<netinet/in.h>#include<unistd.h>#include<sys/types.h>static void Usage(char *proc){ printf("Usage %s [server_ip] [server_port]\n", proc);}int main(int argc, char* argv[]){ if(argc != 3) { Usage(argv[0]); return 1; } //创建套接字 int sock = socket(AF_INET, SOCK_STREAM,0); if(sock < 0) { perror("socket"); return 2; } struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(atoi(argv[2])); server.sin_addr.s_addr = inet_addr(argv[1]); //将创建的套接字,连入指定的网络服务中,这里连到了服务器 if(connect(sock,(struct sockaddr*)&server, sizeof(server)) < 0) { perror("connect111"); return 3; } char buf[1024]; while(1) { printf("Please Enter# "); fflush(stdout); //从键盘写入内容到缓冲区 ssize_t s = read(0, buf, sizeof(buf)-1); if(s >0) { buf[s-1] = 0; printf("server# "); fflush(stdout); //将缓冲区内容通过套接字发送到服务器 write(sock, buf, strlen(buf)); //在从套接字中读取服务器的回应信息 ssize_t _s = read(sock, buf, sizeof(buf)-1); if(_s > 0) { buf[_s] = 0; printf("%s\n", buf); } if(s < 0) { perror("read"); return 4; } } } return 0;}
阅读全文
1 0
- 使用套接字实现简单TCP服务器客户端模型
- 用管道或套接字实现客户端服务器模型
- 套接字实现Tcp服务器
- 套接字实现TCP服务器
- TCP套接字编程实现简单的并发服务器
- TCP、UDP套接字编程(简单客户/服务器实现)
- TCP阻塞套接字客户端和服务器
- TCP SOCKET服务器|客户端简单实现
- TCP服务器、客户端的简单实现
- JAVA实现简单的客户端服务器模型
- 实现简单UDP服务器客户端模型
- Java 利用套接字Socket实现简单的服务器与客户端通信
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- 使用TCP套接字实现文件服务器
- 简单的,使用套接字实现TCP通信(用线程实现并发)
- TCP套接字编程模型
- TCP套接字编程模型
- tcp套接字编程模型
- Android IO File
- Got error 28 from storage engine 解决方法
- 在java中连接Mysql的参数(一)
- 佳能7760DSDK开发
- linux-一次load高但是cpu占用率低的排查
- 使用套接字实现简单TCP服务器客户端模型
- Activity四种启动模式
- MyBatis插入空值时指定的JdbcType
- 2017暑期目标
- 在ThinkPhp3.2 中 href 问题
- windows php7 安装 mongodb 扩展
- iOS控件-UICollectionView基本使用详解
- PAT乙级1004. 成绩排名 (20)
- java读取properties文件