socket操作
1.1 创建socket
int socket(int domain, int type, int protocol);
domain: 确定通信的特性
AF_INET IPv4因特网域
AF_INET6 IPv6因特网域
AF_UNIX UNIX域
AF_UNSPEC 未指定
type: 指定套接字的类型
SOCK_DGRAM 长度固定的、无连接的不可靠报文传递
SOCK_RAW IP协议的数据报接口(POSIX.1中可选)
SOCK_SEQPACKET 长度固定、有序、可靠的面向连接报文传递
SOCK_STREAM 有序、可靠、双向的面向连接字节流
protocol参数通常是0,表示按给定的域和套接字类型选择默认协议。当同一域和套接字类型支持多个协议的时候,可以使用protocol参数选择一个特定的协议。
AF_INET通信域中套接字类型SOCK_STREAM的默认协议是TCP(传输控制协议)
AF_INET通信与中套接字类型SOCK_DGRAM的默认协议是UDP(用户数据报协议)
1.2 绑定地址(server)
int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
sockfd: 要绑定的套接字
my_addr: 地址结构体
addrlen: 结构体长度,通常为sizeof(my_addr)
1.2.1 struct sockaddr
该结构体定义了地址信息
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
1.2.2 网络字节转换
网络中的数据格式为大端,所以需要将小端存储的数据转换成为大端存储,一下为网络字节序和本地字节序(小端)之间转换函数
uint32_t htonl(uint32_t hostint32); /// host to net long(uint32_t)
uint16_t htons(uint16_t hostint16); /// host to net short(uint16_t)
uint32_t ntohl(uint32_t netint32); /// net to host long(uint32_t)
uint16_t ntohs(uint16_t netint16); /// net to host short(uint16_t)
1.2.3inet_pton
int inet_pton(int af, const char *src, void *dst);
将字符串类型的地址转换成为struct sockaddr_in::sin_addr类型
af: 通信特性
src: 地址字符串
dst:truct sockaddr_in::sin_addr类型,长度必需为sizeof(struct in_addr).
1.2.4 查询地址
#include <netdb.h>
struct hostent *gethostent(void); ///(打开主机数据文件)返回struct hostent
void endhostent(void); /// 关闭打开的主机数据文件
void sethostent(int stayopen); ///打开主机数据文件
struct hostent {
char *h_name; /// 主机名
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
. . .
};
设置地址的例子:
struct sockaddr_in laddr;
laddr.sin_family = AF_INET;
laddr.sin_port = hotns(atoi(SERVERPORT));
inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);
1.3 建立连接(client)
int connect(int sockfd, const struct sockaddr* my_addr, socket_t addrlen);
sockfd: 套接字
my_addr: 想连接的服务器的地址
addrlen: 地址结构的长度,通常为sizeof(my_addr)
1.4 服务器宣告可以接受连接请求 listen
int listen(int sockfd, int backlog);
backlog: 该进程最大的入队连接请求数
1.5 获得连接请求并建立连接 accept
int accept(int sockfd,struct sockaddr*my_addr, socket_t*addrlen);
my_addr: 用户地址
addrlen: 用户地址长度
1.6 发数据(client)
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
sockfd: 套接字
buf: 要发送数据的buf
nbytes: buf长度
flags: 发送标识
MSG_DONTROUTE: 勿将数据路由出本地网络
MSG_DONTWAIT: 允许非阻塞操作
MSG_EOR: 如果协议支持,此为记录结束
MSG_OOB: 如果协议支持,发送外带数据
1.7 收数据(server)
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
sockfd: 套接字
buf: 接收数据的buf
nbytes: buf长度
flags: 发送标识
MSG_OOB: 如果协议支持,接收外带数据
MSG_PRRK: 返回报文内容而不真正取走报文
MSG_TRUNC: 即使报文被截断,要求返回的是报文的实际长度
MSG_WAITALL: 等待直到所有的数据可用(仅SOCK_STREAM)
mysocket.h
#ifndef MYSOCKET_H_INCLUDED
#define MYSOCKET_H_INCLUDED
#include <iostream>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#define SERVERPORT "1234"
#define SERVERIP "127.0.0.1"
#define MAXBACKLOG 10
#define MAXIPSIZE 20
#define BUFMAXSIZE 1024*1024
#define WRITEFILEPATH "./recvFile"
#define READFILEPATH "./a.tgz"
using namespace std;
#endif // MYSOCKET_H_INCLUDED
client.cpp
#include "mysocket.h"
int main()
{
int iRet = 0;
int sockFd = 0;
struct sockaddr_in serverAddr;
sockFd = socket(AF_INET, SOCK_STREAM, 0);
char sendBuf[BUFMAXSIZE];
if (sockFd < 0) {
cout << "socket is error" << endl;
} else {
cout << "socket is ok" << endl;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET, SERVERIP, &serverAddr.sin_addr);
iRet = connect(sockFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (iRet < 0) {
cout << "connect is error." << endl;
} else {
cout << "connect is ok." << endl;
}
FILE *rfp = fopen(READFILEPATH, "rb+");
while(1) {
iRet = fread(sendBuf, 1, BUFMAXSIZE, rfp);
cout << "fork:fread ret = " << iRet << endl;
if (iRet < 0) {
cout << "fread is error" << endl;
break;
}
iRet = send(sockFd, sendBuf, iRet, 0);
if (iRet < BUFMAXSIZE) {
cout << "fread is eof" << endl;
break;
}
}
fclose(rfp);
return 0;
}
server.cpp
#include "mysocket.h"
int main()
{
int iRet = 0;
int sockFd = 0;
struct sockaddr_in serverAddr, clientAddr;
socklen_t clientLen = 0;
char clientIP[MAXIPSIZE];
char recvBuf[BUFMAXSIZE];
sprintf(recvBuf, "rm %s", WRITEFILEPATH);
system(recvBuf);
memset(recvBuf, 0, BUFMAXSIZE);
int recvLen = 0;
FILE *fp = NULL, *wfp = NULL;
sockFd = socket(AF_INET, SOCK_STREAM, 0); /// create socket
if (sockFd < 0) {
cout << "socket is error" << endl;
} else {
cout << "socket is ok" << endl;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET, "0.0.0.0", &serverAddr.sin_addr);
iRet = bind(sockFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); /// bind addr
if (iRet < 0) {
cout << "bind is error." << endl;
} else {
cout << "bind is ok." << endl;
}
iRet = listen(sockFd, MAXBACKLOG); /// listen
if (iRet < 0) {
cout << "listen is error." << endl;
} else {
cout << "listen is ok." << endl;
}
int newSd;
while(1) {
newSd = accept(sockFd, (struct sockaddr*)&clientAddr, &clientLen);
if (newSd < 0) {
cout << "accept is error : iRet = " << iRet << endl;
break;
}
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, MAXIPSIZE);
cout << "client: " << clientIP << " : " << ntohs(clientAddr.sin_port) << " is connected" << endl;
if (fork() == 0) {
wfp = fopen(WRITEFILEPATH, "ab+");
fp = fdopen ( newSd, "r+" );
while (1) {
iRet = fread ( recvBuf, 1, BUFMAXSIZE, fp );
if (iRet <= 0) {
cout << "recv is done" << endl;
break;
}
fwrite(recvBuf, 1, iRet, wfp);
}
fclose(fp);
fclose(wfp);
}
sleep(1);
}
return 0;
}
阅读(230) | 评论(0) | 转发(2) |
分享到:
相关推荐
基础篇结合示例论述了Delphi的深度编程技术,其中包括9章,分别为:理解Windows消息、进程与线程、自定义组件的编写、文件操作、创建DLL应用程序、两层数据库应用程序、多层数据库应用程序、Socket编程、串口编程;...
Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个...
创建一个基于udp的网络程序流程很简单,具体步骤如下: 创建客户端套接字 发送/接收数据 关闭套接字 代码如下: #coding=utf-8 from socket import * # 1. 创建udp套接字 udp_socket = socket(AF_INET, SOCK_...
EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean...
9.3 利用API函数创建串口通信示例 9.3.1 发送数据部分设计(向串口写数据) 9.3.2 数据部分设计(从串口读数据) 9.3.3 程序的具体设计和实现 9.4 利用SPC0MM组件实现串口通信编程 9.4.1 SPCOMM组件的安装 9.4.2 ...
创建多对多以及增加示例 本节内容梳理 本周作业 第21周 今日知识点概要 上节内容回顾以及URL的补充 视图获取用户请求相关信息以及请求头 模板之继承 模板之导入 上节作业情况 自定义 simple_tag 自定义filter ...
phper 请了解进程调度策略,CPU 时间片,进程控制【创建,销毁,回收,进程信号】与及进程运行流程和基本的进程组,信号中断原理,以及进程之间的关系。 关于进程的更多内容可参考本人前面撸过的文章或是百度了解。...
这是一款使用XPGWifiSDK的开源代码示例APP,可以帮助开发者快速入手,使用XPGWifiSDK开发连接机智云的物联APP。该APP针对的是智能家电中的插座类产品。包括了以下几点插座常用功能: ▪ 插座电源的开关 ▪ 插座定时...
该存储库是一个聊天室的示例,该聊天室是使用具有Node.js(Express)后端和React前端的socket.io创建的。遵循逻辑流程图和组件文件的注释,以了解所有代码背后的工作。 在这里测试: :
EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean...
31_gRPC在Nodejs领域中的静态代码生成及与Java之间的RPC通信 32_IO体系架构系统回顾与装饰模式的具体应用 33_Java NIO深入详解与体系分析 34_Buffer中各重要状态属性的含义与关系图解 35_Java NIO核心类源码解读与...
20_通过Apache Thrift实现Java与Python的RPC调用 21_gRPC深入详解 22_gRPC实践 23_Gradle Wrapper在Gradle项目构建中的最佳实践 24_gRPC整合Gradle与代码生成 25_gRPC通信示例与JVM回调钩子 26_gRPC服务器流式调用...
实例32 优良及差 47 实例33 打印任意一年日历 48 实例34 一年四季的划分 51 第2篇 Java数据处理 第4章 异常处理(教学视频:62分钟) 54 4.1 编译时异常 54 实例35 除0发生的算术异常...
EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证...
2.5流程控制语句58 2.5.1三种基本控制结构58 2.5.2表达式语句和空语句59 2.5.3块语句60 2.5.4if~else分支语句61 2.5.5多路分支switch~case语句69 2.5.6当型循环while语句71 2.5.7直到型循环do~while语句72...
10.4.1 构造器的调用流程及默认构造器 182 10.4.2 自定义构造器需要注意的问题 185 10.4.3 不能继承构造器 186 10.4.4 调用兄弟构造器 187 10.5 单列模式 189 10.6 Java程序的加载过程 190 10.7 小结 ...
2.2.2 MFC应用程序运行流程 50 2.2.3 应用程序窗口 51 2.2.4 消息机制与消息循环 59 2.3 文档与视图 65 2.3.1 文档类结构分析 65 2.3.2 视图类结构分析 65 2.3.3 文档与视图的关系 67 2.3.4 sdi应用程序分析 69 ...