Socket编程实践(3) --Socket API
socket函数
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
创建一个套接字用于通信
参数:
domain:指定通信协议族(protocol family),常用取值AF_INET(IPv4)
type:指定socket类型, 流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW
protocol:协议类型,常用取值0, 使用默认协议
返回值:
成功: 返回非负整数,套接字;
失败: 返回-1
bind函数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
绑定一个本地地址到套接字
参数:
sockfd:socket函数返回的套接字
addr:要绑定的地址
//sockaddr_in结构, bind时需要强制转换成为struct sockaddr*类型
struct sockaddr_in
{sa_family_t sin_family; /* address family: AF_INET */in_port_t sin_port; /* port in network byte order */struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr
{uint32_t s_addr; /* address in network byte order */
};
/**示例:INADDR_ANY的使用, 绑定本机任意地址**/
int main()
{int listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd == -1)err_exit("socket error");struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8001);//绑定本机的任意一个IP地址, 作用同下面两行语句addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_aton("127.0.0.1", &addr.sin_addr);//addr.sin_addr.s_addr = inet_addr("127.0.0.1");if (bind(listenfd, (const struct sockaddr *)&addr, sizeof(addr)) == -1)err_exit("bind error");elsecout << "bind success" << endl;
}
listen函数
int listen(int sockfd, int backlog);
listen函数应该用在调用socket和bind函数之后, 并且用在调用accept之前, 用于将一个套接字从一个主动套接字转变成为被动套接字。
backlog说明:
对于给定的监听套接口,内核要维护两个队列:
1、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程(SYN_RCVD状态)
2、已完成连接的队列(ESTABLISHED状态)
但是两个队列长度之和不能超过backlog
backlog推荐使用SOMAXCONN(3.13.0-44-generic中该值为128), 使用等待队列的最大值;
Man-Page中的listen说明:
listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that
will be used to accept incoming connection requests using accept(2).
The sockfd argument is a file descriptor that refers to a socket of type SOCK_STREAM or
SOCK_SEQPACKET.
The backlog argument defines the maximum length to which the queue of pending connections for
sockfd may grow. If a connection request arrives when the queue is full, the client may receive
an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission,
the request may be ignored so that a later reattempt at connection succeeds.
If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn(Ubuntu 14.04 该值为128), then it is silently truncated to that value; the default value in this file is 128. In kernels
before 2.4.25, this limit was a hard coded value, SOMAXCONN, with the value 128.
accept函数
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
从已完成连接队列返回第一个连接(the first connection request on the queue of pending connections for the listening
socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket.
The newly created socket is not in the listening state),如果已完成连接队列为空,则阻塞。The original
socket sockfd is unaffected by this call.
参数:
sockfd:服务器套接字
addr:将返回对等方的套接字地址, 不关心的话, 可以设置为NULL
addrlen:返回对等方的套接字地址长度, 不关心的话可以设置成为NULL, 否则一定要初始化
返回值:
On success, these system calls return a non-negative integer that is a descriptor for the accepted
socket. On error, -1 is returned, and errno is set appropriately.
connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
建立一个连接至addr所指定的套接字
参数:
sockfd:未连接套接字
addr:要连接的套接字地址
addrlen:第二个参数addr长度
示例:echo server/client实现
//server端代码
int main()
{int listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd == -1)err_exit("socket error");struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8001);addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(listenfd, (const struct sockaddr *)&addr, sizeof(addr)) == -1)err_exit("bind error");if (listen(listenfd, SOMAXCONN) == -1)err_exit("listen error");char buf[512];int readBytes;struct sockaddr_in clientAddr;//谨记: 此处一定要初始化
socklen_t addrLen = sizeof(clientAddr);while (true){int clientfd = accept(listenfd, (struct sockaddr *)&clientAddr, &addrLen);if (clientfd == -1)err_exit("accept error");//打印客户IP地址与端口号cout << "Client information: " << inet_ntoa(clientAddr.sin_addr)<< ", " << ntohs(clientAddr.sin_port) << endl;memset(buf, 0, sizeof(buf));while ((readBytes = read(clientfd, buf, sizeof(buf))) > 0){cout << buf;if (write(clientfd, buf, readBytes) == -1)err_exit("write socket error");memset(buf, 0, sizeof(buf));}if (readBytes == 0){cerr << "client connect closed..." << endl;close(clientfd);}else if (readBytes == -1)err_exit("read socket error");}close(listenfd);
}
//client端代码
int main()
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1)err_exit("socket error");//填写服务器端口号与IP地址struct sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8001);serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");if (connect(sockfd, (const struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)err_exit("connect error");char buf[512];while (fgets(buf, sizeof(buf), stdin) != NULL){if (write(sockfd, buf, strlen(buf)) == -1)err_exit("write socket error");memset(buf, 0, sizeof(buf));int readBytes = read(sockfd, buf, sizeof(buf));if (readBytes == 0){cerr << "server connect closed... \nexiting..." << endl;break;}else if (readBytes == -1)err_exit("read socket error");cout << buf;memset(buf, 0, sizeof(buf));}close(sockfd);
}
附-Makefile
.PHONY: clean all
CC = g++
CPPFLAGS = -Wall -g -pthread -std=c++11
BIN = server client
SOURCES = $(BIN.=.cpp)all: $(BIN)
$(BIN): $(SOURCES) clean:-rm -rf $(BIN) bin/ obj/ core
Socket编程实践(3) --Socket API相关推荐
- Socket编程实践(2) --Socket编程导引
什么是Socket? Socket可以看成是用户进程与内核网络协议栈的接口(编程接口, 如下图所示), 其不仅可以用于本机进程间通信,可以用于网络上不同主机的进程间通信, 甚至还可以用于异构系统之间的 ...
- Socket编程实践(6) --TCP服务端注意事项
僵尸进程处理 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 sign ...
- Socket编程实践(10) --select的限制与poll的使用
select的限制 用select实现的并发服务器,能达到的并发数一般受两方面限制: 1)一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n(number)来调整或 ...
- socket编程基础2(socket API函数介绍)
"一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...
- C# socket编程实践——支持广播的简单socket服务器
在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...
- Socket编程概念和 Socket之异步TCP客户端断线重连
一:什么是SOCKET socket的英文原义是"孔"或"插座".作为进程通信机制,取后一种意思.通常也称作"套接字",用于描 ...
- 计算机网络实验 socket编程,计算机网络实验 socket编程
实验三 socket套接字编程实验 一.Sockets编程基础知识 网络编程就是通过计算机网络与其他程序进行通信的程序,Socket编程是网络编程的主流工具. Socket API是实现进程间通信的一 ...
- 计算机网络实验socket编程,计算机网络实验 socket编程
使用连接.终止连接的过程.在数据传输过程中,各数据分组不携带目的地址,而使用连接号(connect ID ).从本质上看,连接是一个管道,收发数据不但顺序一致,而且内容相同. Socket 编程中,双 ...
- socket编程 —— 非阻塞socket (转)---例子已上传至文件中
在上一篇文章 <socket编程--一个简单的例子> http://blog.csdn.net/wind19/archive/2011/01/21/6156339.aspx 中写了一个简单 ...
最新文章
- 新网站如何做好前期SEO优化?
- 利用Swift语言特性,随手写个伪随机数生成器
- POJ 3104 Drying【二分搜索】最大化最小值问题
- 【转】Linux将composer的bin目录放到PATH环境变量中
- DIV Scroll属性
- IDC服务器共享带宽和独享带宽的区别
- 每天一个Linux命令(3):ls命令
- (原創) 如何控制DE2 VGA輸出時某座標的顏色? (IC Design) (DE2) (Quartus II)
- sentinelsat包介绍
- mysql不配置环境变量可以吗_MySQL配置环境变量
- iOS 深度跳转(scheme、universal link)
- Flink Forward Asia Hackathon (2021) 回顾
- CVPR2021提出的一些新数据集汇总
- Excel编程——自动换行
- leetcode 1359. Count All Valid Pickup and Delivery Options(有效的快递序列数目)
- 【单片机毕业设计】【mcuclub-103】智能花盆 | 智能养殖箱 | 多功能花盆 | 多功能养殖箱【仿真设计】
- canvas小虫子(利用canvas形成多个形状类似虫子的线条)
- 和女友一起学技术,她去了字节,我去了华为
- SEO流量变现,看这个项目就够了!
- 李国庆是如何被“踢出”当当的?