linux socket基础
来源:互联网 发布:ubuntu 离线安装jre 编辑:程序博客网 时间:2024/05/18 00:21
socket起源于unix, 而unix / linux 基本哲学之一就是“一切皆文件”,都可以用“open -> write/read -> close” 模式来操作。socket 就是该模式的一个实现,socket即是一种特殊的文件,一些socket 函数就是对其操作 (open -> I/O操作 -> close)。
一个简单的客户端获取服务器时间的例子:
服务器代码:
服务器实现socket的简单逻辑
1 设置 sockaddr_in 的基本信息
2 创建一个 socket
3 bind 将 socket 与 sockaddr_in 信息绑定到一起
4 listen 监听这个socket 这个时候就可以监听这个 socket 地址了 (客户端通过 socket connect 向服务器发送了一个连接请求)
5 accept TCP服务器监听到请求 就可以通过这个函数取接收请求了
</pre><pre name="code" class="plain">#include <iostream>#include "unp.h"#include "my_err.h"#define DEFAULT_PORT 8000int main(int argc, const char * argv[]){ int listenfd, connfd; struct sockaddr_in servaddr; //server address 服务地址结构体 存储服务的必要信息 char buff[MAXLINE]; // MAXLINE = 4096 time_t ticks; listenfd = Socket(AF_INET, SOCK_STREAM, 0); //创建socket Socket经过封装了 返回id < 0 表示创建失败 具体细节看 my_err.h文件 bzero(&servaddr, sizeof(servaddr)); //清空这段内存 相当于 初始化 servaddr = 0 servaddr.sin_family = AF_INET; //IPV4 协议 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //自动获取本机的ip 地址 servaddr.sin_port = htons(DEFAULT_PORT); //端口号 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); //把一个特定的地址 绑定到socket 把设置的servaddr 服务器信息绑定到socket Listen(listenfd, LISTENQ);//监听这个socket 第1个参数 socket的描述字 第二个参数 socket可排队的最大连接个数 for ( ; ; ){ std::cout << "wait connect" << std::endl; connfd = Accept(listenfd, (SA *) NULL, NULL); //如果有连接 这个函数会取接受请求 这个默认是阻塞函数 取不到接受不会往下执行 有不阻塞模式//第一个参数 socket的描述字 第二个参数 客户端的 servaddr信息 第三个参数 客户端 servaddr的 所占字节数 2,3参数不关心 可置空//返回一个唯一的连接id//这样连接就建立好了 之后可以开始网络的I/O操作了 类同于普通文件的读写操作 ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); Write(connfd, buff, strlen(buff)); //通过上面唯一id 往这个连接写入东西 客户端会收到这个写入 从而取得服务器发过去的数据 实现交互 Close(connfd); } std::cout << "Hello, World!\n"; return 0;}
客户端代码:客户端实现socket 简单逻辑
1 设置 sockaddr_in 的基本信息
2 创建一个 socket
3 connect 连接到设置的服务器
4 如果服务器有write, 通过read读取服务器发过来的信息,同样客户端也可write, 服务器也可read
</pre><pre name="code" class="plain">#include <iostream>#include "unp.h"#include "my_err.h"int main(int argc, const char * argv[]){ int sockfd, n; char recvline[MAXLINE + 1]; struct sockaddr_in servaddr;// if (argc != 2)// err_quit("usage: a.out <Ipaddress>"); if ( (sockfd = Socket(AF_INET, SOCK_STREAM, 0)) <0) err_sys("socket error"); //创建socket //第一个参数 family 指定协议族 常用的协议族 AF_INET(IPV4) AF_INET6(IPV6) AF_UNIX 等等//第二个参数 type 指定socket的类型 SOCK_STREAM SOCK_DGRAW SOCK_RAW SOCK_PACKET SOCK_SEQPACKET 等等//第三个参数 protocol 指定协议 IPPROTO_TCP IPPTOTO_UDP IPPROTO_SCTP IPPROTO_TIPC 分别对应TCP UDP SCTP TIPC 传输协议//注:上面的 type 和 protocol 并不能随意组合, 如:SOCK_STREAM 与 IPPTOTO_UDP 不能组合, 当protocol为0时,根据family 和 type 选择默认传输协议 例:ANF_INET 和 SOCK_STREAM 选择TCP协议 ANF_INET 和 SOCK_DGRAW 选择 UDP协议 bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(8000); if (inet_pton(AF_INET, "192.168.1.59", &servaddr.sin_addr) <= 0) //127.0.0.1 作用将ip地址转换完后 赋值到 servaddr的地址中去 err_quit("inet_pton error for %s", argv[1]);////inet_pton 是linux下的地址转换函数 将ip地址的 点分十进制 和 整数 之间转换 if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0 )//连接指定的服务器 err_sys("connect error"); while ( (n = read(sockfd, recvline, MAXLINE)) > 0 ) {//读取服务器发过来的信息 >0 表示有数据 recvline[n] = 0; if (fputs(recvline , stdout) == EOF) err_sys("fputs error"); } if (n < 0 ) err_sys("read error"); return 0;}
my_err.h 文件
#ifndef time1_my_err_h#define time1_my_err_h#include <errno.h> /* for definition of errno */#include <stdarg.h> /* ISO C variable aruments */static void err_doit(int, int, const char *, va_list);/* * Nonfatal error related to a system call. * Print a message and return. */voiderr_ret(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(1, errno, fmt, ap); va_end(ap);}/* * Fatal error related to a system call. * Print a message and terminate. */voiderr_sys(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(1, errno, fmt, ap); va_end(ap); exit(1);}/* * Fatal error unrelated to a system call. * Error code passed as explict parameter. * Print a message and terminate. */voiderr_exit(int error, const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(1, error, fmt, ap); va_end(ap); exit(1);}/* * Fatal error related to a system call. * Print a message, dump core, and terminate. */voiderr_dump(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(1, errno, fmt, ap); va_end(ap); abort(); /* dump core and terminate */ exit(1); /* shouldn't get here */}/* * Nonfatal error unrelated to a system call. * Print a message and return. */voiderr_msg(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(0, 0, fmt, ap); va_end(ap);}/* * Fatal error unrelated to a system call. * Print a message and terminate. */voiderr_quit(const char *fmt, ...){ va_list ap; va_start(ap, fmt); err_doit(0, 0, fmt, ap); va_end(ap); exit(1);}/* * Print a message and return to caller. * Caller specifies "errnoflag". */static voiderr_doit(int errnoflag, int error, const char *fmt, va_list ap){ char buf[MAXLINE]; vsnprintf(buf, MAXLINE, fmt, ap); if (errnoflag) snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s", strerror(error)); strcat(buf, "\n"); fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(NULL); /* flushes all stdio output streams */}intSocket(int family, int type, int protocol){intn; if ( (n = socket(family, type, protocol)) < 0)err_sys("socket error");return(n);}voidBind(int fd, const struct sockaddr *sa, socklen_t salen){if (bind(fd, sa, salen) < 0)err_sys("bind error");}voidClose(int fd){if (close(fd) == -1)err_sys("close error");}voidWrite(int fd, void *ptr, size_t nbytes){if (write(fd, ptr, nbytes) != nbytes)err_sys("write error");}intAccept(int fd, struct sockaddr *sa, socklen_t *salenptr){intn; again:if ( (n = accept(fd, sa, salenptr)) < 0) {#ifdefEPROTOif (errno == EPROTO || errno == ECONNABORTED)#else if (errno == ECONNABORTED)#endif goto again; else err_sys("accept error");}return(n);}voidListen(int fd, int backlog){char*ptr; /*4can override 2nd argument with environment variable */if ( (ptr = getenv("LISTENQ")) != NULL)backlog = atoi(ptr); if (listen(fd, backlog) < 0)err_sys("listen error");}#endif
对比 window socket http://blog.csdn.net/tutuboke/article/details/45799667
2 1
- linux socket开发基础
- Linux Socket基础
- Linux Socket基础
- Linux Socket基础
- Linux Socket 基础
- 基础linux的socket
- Linux socket编程基础
- Linux Socket基础介绍
- linux socket基础
- Linux socket编程基础
- linux socket 编程基础
- Linux下Socket编程一 socket 基础
- Linux 下Socket编程基础
- Linux 下Socket编程基础
- Linux 下Socket编程基础
- Linux下socket编程基础
- Linux socket之一:基础函数
- Linux 下Socket编程基础
- 阶段性学习总结(2)
- PKUSC预热__被水题虐QoQ
- 【学习笔记】JavaScript编码规范- 注释
- 使用Python快速实现显示器关闭和锁住桌面
- Oracle执行计划中的索引
- linux socket基础
- 一次非常有意思的SQL优化经历:从30248.271s到0.001s
- 分布式进阶(三)Ubuntu 14.04 之JDK安装
- 优化js
- sencha项目的创建
- SQL Server FOR XML PATH 语句的应用
- ubuntu安装PostgreSQL
- 数据规范化常用方法
- 金字塔图像分割原理解析与示例[opencv]