赞
踩
socket被命名之后,还不能马上接受客户连接,我们需要使用如下系统调用来创建一个 监听队列以存放待处理的客户连接:
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <csignal>
- #include <cassert>
- #include <unistd.h>
-
- #include "include/algorithm_text.h"
-
- static bool stop = false;
- static void handle_term(int sig){
- stop = true;
- }
- int main(int argc,char* argv[]) {
- //参考链接 https://blog.51cto.com/u_15284125/2988992
- //signal函数 第一参数是指需要进行处理的信号,第二个参数是指 处理的方式(系统默认/忽略/捕获)
- //SIGTERM 请求中止进程,kill命令缺省发送 交给handle_term函数进行处理
- signal(SIGTERM,handle_term);
- if (argc < 3){
- //basename 参考链接 https://blog.csdn.net/Draven_Liu/article/details/38235585
- //假设路径为 nihao/nihao/jhhh/txt.c
- //basename函数并不会关心路径是否正确,文件是否存在,只不过是把路径上除了最后的txt.c 这个文件名字其他的东西都删除了然后返回txt.c而已
- std::cout << "usage:" <<basename(argv[0]) << "ip_address port_number backlog\n"<<std::endl;
- }
- //argv[1] ip地址
- //argv[2] 端口号
- //argv[3] 日志级别
- const char* ip = argv[1];
- //atoi 把字符串转换成一个整数
- //参考链接 https://www.runoob.com/cprogramming/c-function-atoi.html
- int port = atoi(argv[2]);
- int backlog = atoi(argv[3]);
- //socket编程 第一个参数表示使用哪个底层协议族,对 TCP/IP协议族而言,该参数应该设置为PF_INET
- //对 TCP/IP协议族而言,其值取SOCK_STREAM表示传输层使用TCP协议
- //第三个参数是在前两个参数构成的协议集合下,再选择一个具体的协议 设置为0 ,表示使用默认协议
- int sock = socket(PF_INET,SOCK_STREAM,0);
- //断言 如果不正确 不会往下继续执行
- assert(sock>=0);
- //创建一个IPv4 socket地址
- //TCP/IP 协议族sockaddr_in 表示IPv4专用socket地址结构体
- struct sockaddr_in address;
- // bzero() 会将内存块(字符串)的前n个字节清零;
- // s为内存(字符串)指针,n 为需要清零的字节数。
- // 在网络编程中会经常用到。
- bzero(&address,sizeof (address));
- address.sin_family = AF_INET;
- //int inet_pton(int af,const char* src,void* dst)
- //af 指定地址族 AF_INET 或者 AF_INET6
- //inet_pton函数成功返回1 失败返回0,并且设置errno
- //errno 表示各种错误
- // inet_pton 将字符串表示的IP地址src(使用点分十进制表示的IPv4地址和使用十六进制表示的IPv6)转换成网络字节序整数表示的IP地址,并把转换的结果存储在dst指向的内存中
- inet_pton(AF_INET,ip,&address.sin_addr);
- //const char* inet_ntop(int af,const char* src,void* dst,socklen_t cnt)
- //inet_tpon函数和inet_pton进行相反的转换,前三个参数的含义与其相同,最后一个参数cnt指定目标存储单元的大小
- //成功 返回目标单元的地址 失败返回NULL 并且设置errno
- address.sin_port = htons(port);
- //bind将 my_addr所指的socket地址(2)分配给未命名的sockfd(1)文件描述符,addrlen参数(3)指出该socket地址的长度。
- int ret = bind(sock,(struct sockaddr*)&address,sizeof (address));
- assert(ret != -1);
- ret = listen(sock,backlog);
- //循环等待连接 直到有SIGTERM信号将其中断
- while(!stop){
- sleep(1);
- }
- //关闭 socket
- close(sock);
- return 0;
- }
5 . 5 接受连接
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <csignal>
- #include <cassert>
- #include <unistd.h>
-
- #include "include/algorithm_text.h"
-
- int main(int argc,char* argv[]) {
- if (argc <= 2){
- printf("usage:%s ip_address port_number\n", basename(argv[0]));
- return 1;
- }
- const char* ip = argv[1];
- int port = atoi(argv[2]);
- struct sockaddr_in address{};
- bzero(&address,sizeof (address));
- address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&address.sin_addr);
- //htons 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
- address.sin_port = htons(port);
- int sock = socket(PF_INET,SOCK_STREAM,0);
- assert(sock >= 0);
- int ret = bind(sock,(struct sockaddr*)&address,sizeof (address));
- assert(ret != -1);
- ret = listen(sock,5);
- //等待20秒 等待客户端连接和相关操作 (掉线/退出)完成
- sleep(20);
- struct sockaddr_in client;
- socklen_t client_addrlength = sizeof (client);
- int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);
- if (connfd < 0){
- printf("errno is:%d\n",errno);
- } else{
- //接受连接成功 则打印客户端的IP地址和端口号
- char remote[INET_ADDRSTRLEN];
- printf("connected with ip:%s and port:%d\n",
- inet_ntop(AF_INET,&client.sin_addr,remote,INET_ADDRSTRLEN),
- // 将一个无符号短整形数从网络字节顺序转换为主机字节顺序
- ntohs(client.sin_port));
- close(connfd);
- }
- close(sock);
- return 0;
- }
发送端代码
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <cassert>
- #include <unistd.h>
- #include <cstdio>
- #include <cstdlib>
-
- #include "include/algorithm_text.h"
-
-
- int main(int argc,char* argv[]) {
- if (argc <= 2){
- printf("usage:%s ip_server_address port_number\n", basename(argv[0]));
- return 1;
- }
- const char* ip = argv[1];
- int port = atoi(argv[2]);
- struct sockaddr_in server_address{};
- bzero(&server_address,sizeof (server_address));
- server_address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&server_address.sin_addr);
- //htons 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
- server_address.sin_port = htons(port);
- int sock_fd = socket(PF_INET,SOCK_STREAM,0);
- assert(sock_fd >= 0);
- if (connect(sock_fd,(struct sockaddr*)&server_address,sizeof (server_address))<0){
- printf("connected failed.\n");
- } else{
- const char* oob_data = "abc";
- const char* normal_data = "123";
- send(sock_fd,normal_data, strlen(normal_data),0);
- send(sock_fd,oob_data, strlen(oob_data),MSG_OOB);
- send(sock_fd,normal_data, strlen(normal_data),0);
- }
-
- close(sock_fd);
- return 0;
- }
接收端代码
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <cassert>
- #include <unistd.h>
- #include <cstdio>
- #include <cstdlib>
-
- #include "include/algorithm_text.h"
- #define BUF_SIZE 1024
-
-
- int main(int argc,char* argv[]) {
- if (argc <= 2){
- printf("usage:%s ip_server_address port_number\n", basename(argv[0]));
- return 1;
- }
- const char* ip = argv[1];
- int port = atoi(argv[2]);
- struct sockaddr_in server_address{};
- bzero(&server_address,sizeof (server_address));
- server_address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&server_address.sin_addr);
- //htons 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
- server_address.sin_port = htons(port);
- int sock_fd = socket(PF_INET,SOCK_STREAM,0);
- assert(sock_fd >= 0);
- int ret = bind(sock_fd,(struct sockaddr*)&server_address,sizeof (server_address));
- assert(ret != -1);
-
- ret = listen(sock_fd,5);
- assert(ret != -1);
-
- struct sockaddr_in client{};
- socklen_t client_addrlength = sizeof (client);
- int connfd = accept(sock_fd,(struct sockaddr*)&client,&client_addrlength);
- if (connfd < 0){
- printf("errno is %d\n",errno);
- } else{
- char buffer[BUF_SIZE];
- memset(buffer,'\0',BUF_SIZE);
- ret = recv(connfd,buffer,BUF_SIZE-1,0);
- printf("got %d bytes of normal data '%s' \n",ret,buffer);
-
- memset(buffer,'\0',BUF_SIZE);
- ret = recv(connfd,buffer,BUF_SIZE-1,MSG_OOB);
- printf("got %d bytes of oob data '%s' \n",ret,buffer);
-
- memset(buffer,'\0',BUF_SIZE);
- ret = recv(connfd,buffer,BUF_SIZE-1,0);
- printf("got %d bytes of normal data '%s' \n",ret,buffer);
-
- close(connfd);
- }
- close(sock_fd);
- return 0;
- }
5.8.2 UDP数据读写
- int sock = socket(PF_INET,SOCK_STREAM,0);
- assert(sock >= 0);
- int reuse = 1;
- setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
-
- struct sockaddr_in address{};
- bzero(&address,sizeof(address));
- address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&address.sin_addr);
- address.sin_port = htons(port);
- int ret = bind(sock,(struct sockaddr*)&address,sizeof (address));
修改TCP发送缓冲区的客户端程序
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <cassert>
- #include <unistd.h>
- #include <cstdio>
- #include <cstdlib>
-
- #include "include/algorithm_text.h"
- #define BUF_SIZE 1024
-
-
- int main(int argc,char* argv[]) {
- if (argc <= 2){
- printf("usage:%s ip_server_address port_number\n", basename(argv[0]));
- return 1;
- }
- const char* ip = argv[1];
- int port = atoi(argv[2]);
- struct sockaddr_in server_address{};
- bzero(&server_address,sizeof (server_address));
- server_address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&server_address.sin_addr);
- //htons 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
- server_address.sin_port = htons(port);
- int sock_fd = socket(PF_INET,SOCK_STREAM,0);
- assert(sock_fd >= 0);
-
- int send_buf = atoi(argv[3]);
- int len = sizeof (send_buf);
- //先设置TCP发送缓冲区的大小,然后立即读取数据
- setsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,&send_buf,len);
- getsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,&send_buf,(socklen_t*)&len);
- printf("the tcp send buffer size after setting is %d\n", send_buf);
- if (connect(sock_fd,(struct sockaddr*)&server_address,sizeof (server_address))!=-1){
- char buffer[BUF_SIZE];
- memset(buffer, 'a', BUF_SIZE);
- send(sock_fd, buffer, BUF_SIZE, 0);
- }
- close(sock_fd);
- return 0;
- }
修改TCP接收缓冲区的服务器程序
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <cassert>
- #include <unistd.h>
- #include <cstdio>
- #include <cstdlib>
-
- #include "include/algorithm_text.h"
- #define BUF_SIZE 1024
-
-
- int main(int argc,char* argv[]) {
- if (argc <= 2){
- printf("usage:%s ip_server_address port_number\n", basename(argv[0]));
- return 1;
- }
- const char* ip = argv[1];
- int port = atoi(argv[2]);
- struct sockaddr_in server_address{};
- bzero(&server_address,sizeof (server_address));
- server_address.sin_family = AF_INET;
- inet_pton(AF_INET,ip,&server_address.sin_addr);
- //htons 将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian)
- server_address.sin_port = htons(port);
- int sock_fd = socket(PF_INET,SOCK_STREAM,0);
- assert(sock_fd >= 0);
-
- int recv_buf = atoi(argv[3]);
- int len = sizeof (recv_buf);
- //先设置TCP接收缓冲区的大小,然后立即读取数据
- setsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,&recv_buf,len);
- getsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,&recv_buf,(socklen_t*)&len);
- printf("the tcp receive buffer size after setting is %d\n", recv_buf);
-
- int ret = bind(sock_fd,(struct sockaddr*)&server_address,sizeof (server_address));
- assert(ret != -1);
-
- struct sockaddr_in client{};
- socklen_t client_addrlength = sizeof (client);
- int connfd = accept(sock_fd,(struct sockaddr*)&client,&client_addrlength);
- if (connfd < 0){
- printf("errno is:%d\n",errno);
- } else{
- char buffer[BUF_SIZE];
- memset(buffer,'\0',BUF_SIZE);
- while (recv(connfd,buffer,BUF_SIZE-1,0)>0){}
- close(connfd);
-
- }
-
- close(sock_fd);
- return 0;
- }
访问daytime服务
- #include <iostream>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <cstring>
- #include <cassert>
- #include <unistd.h>
- #include <cstdio>
- #include <cstdlib>
- #include <netdb.h>
-
- #include "include/algorithm_text.h"
- #define BUF_SIZE 1024
-
-
- int main(int argc,char* argv[]) {
- assert(argc == 2);
- char* host = argv[1];
- //获取目标主机地址信息
- struct hostent* hostinfo = gethostbyname(host);
- assert(hostinfo);
- //获取daytime服务信息
- struct servent* servinfo = getservbyname("daytime","tcp");
- assert(servinfo);
- printf("daytime port is %d\n", ntohs(servinfo->s_port));
-
- struct sockaddr_in address{};
- address.sin_family = AF_INET;
- address.sin_port = servinfo->s_port;
- /* 注意下面示码,因为h_addr_list本身是使用网络字节序的地址列表,所以使用其中的IP地址时,
- * 无须对目标IP地址转换字节序*/
- address.sin_addr = *(struct in_addr*)*hostinfo->h_addr_list;
- int sockfd = socket(AF_INET,SOCK_STREAM,0);
- int result = connect(sockfd,(struct sockaddr*)&address,sizeof (address));
- assert(result != -1);
- char buffer[128];
- result = read(sockfd,buffer,sizeof (buffer));
- assert(result > 0);
- buffer[result] = '\0';
- printf("the day tiem is: %s",buffer);
- close(sockfd);
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。