linux下socket编程基础

合集下载

linux socket编程基础(必读)

linux  socket编程基础(必读)
void bzero(void * s,int n):将参数 s 指定的内存的前 n 个字节设置 为0,通常它用来将套接字地址清0。
(2) void bcopy(const void * src,void * dest,int n):从参数 src 指定 的内存区域拷贝指定数目的字节内容到参数 dest 指定的内存区域。
在调用函数 connect 之前,客户机需要指定服务器进程的套接字地址。客户 机一般不需要指定自己的套接字地址(IP 地址和端口号),系统会自动从1024 至5000的端口号范围内为它选择一个未用的端口号,然后以这个端口号和本机 的 IP 地址填充这个套接字地址。
客户机调用函数 connect 来主动建立连接。这个函数将启动 TCP 协议的3次 握手过程。在建立连接之后或发生错误时函数返回。连接过程可能出现的错误情 况有:
(2) 如果远程 TCP 协议返回一个 RST 数据段,函数立即以错误返回,错 误类型为 ECONNREFUSED。当远程机器在 SYN 数据段指定的目的端口号处
没有服务进程在等待连接时,远程机器的 TCP 协议将发送一个 RST 数据段,向 客户机报告这个错误。客户机的 TCP 协议在接收到 RST 数据段后不再继续发送 SYN 数据段,函数立即以错误返回。
(3) int bcmp(const void * s1,const void * s2,int n):比较参数 s1指 定的内存区域和参数 s2指定的内存区域的前 n 个字节内容,如果相同则返回0, 否则返回非0。
注:以上函数的原型定义在 strings.h 中。 以 mem 开头的函数有: (1) void * memset(void * s,int c,size_t n):将参数 s 指定的内存区 域的前 n 个字节设置为参数 c 的内容。 (2) void * memcpy(void * dest,const void * src,size_t n):功能同 bcopy (),区别:函数 bcopy()能处理参数 src 和参数 dest 所指定的区域有重叠的 情况,memcpy()则不能。 (4) int memcmp(const void * s1,const void * s2,size_t n):比较参 数 s1和参数 s2指定区域的前 n 个字节内容,如果相同则返回0,否则返回非0。 注:以上函数的原型定义在 string.h 中。 9、 基本套接字函数 (1) socket() #include<sys/types.h> #include<sys/socket.h>

Linux的SOCKET编程详解

Linux的SOCKET编程详解

Linux的SOCKET编程详解1. 网络中进程之间如何通信进程通信的概念最初来源于单机系统。

由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如UNIX BSD有:管道(pipe)、命名管道(named pipe)软中断信号(signal)UNIX system V有:消息(message)、共享存储区(shared memory)和信号量(semaphore)等.他们都仅限于用在本机进程之间通信。

网间进程通信要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。

为此,首先要解决的是网间进程标识问题。

同一主机上,不同进程可用进程号(process ID)唯一标识。

但在网络环境下,各主机独立分配的进程号不能唯一标识该进程。

例如,主机A赋于某进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了。

其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。

因此,网间进程通信还要解决多重协议的识别问题。

其实TCP/IP协议族已经帮我们解决了这个问题,网络层的―ip地址‖可以唯一标识网络中的主机,而传输层的―协议+端口‖可以唯一标识主机中的应用程序(进程)。

这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。

就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说―一切皆s ocket‖。

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。

socket编程入门(经典版)

socket编程入门(经典版)

(struct sockaddr *)&cliaddr, &cliaddr_len); n = read(connfd, buf, MAXLINE); printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); write(connfd, buf, n); close(connfd); } }
2.1. 最简单的TCP网络程序 请点评
下面通过最简单的客户端/服务器程序的实例来学习socket API。 server.c的作用是从客户端读字符,然后将每个字符转换为大写并回送给客户端。
/* server.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #define MAXLINE 80 #define SERV_PORT 8000 int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int i, n; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 20); printf("Accepting connections ...\n"); while (1) { cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd,

linux c语言 判断端口是否已经关闭的方法

linux c语言 判断端口是否已经关闭的方法

在Linux下,可以使用C语言中的socket编程来判断一个端口是否已经关闭。

以下是一个简单的示例代码:c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>int main(int argc, char *argv[]) {int sockfd;struct sockaddr_in serv_addr;char buffer[1024];int n;if (argc != 2) {fprintf(stderr, "Usage: %s <port>\n", argv[0]);exit(EXIT_FAILURE);}sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);}memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = INADDR_ANY;serv_addr.sin_port = htons(atoi(argv[1])); // 转换为网络字节序if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("bind");exit(EXIT_FAILURE);}if (listen(sockfd, 10) < 0) {perror("listen");exit(EXIT_FAILURE);}while (1) {n = sizeof(serv_addr);int connfd = accept(sockfd, (struct sockaddr *)&serv_addr, &n);if (connfd < 0) {perror("accept");exit(EXIT_FAILURE);}printf("Accept connection from %s:%d\n", inet_ntoa(serv_addr.sin_addr),ntohs(serv_addr.sin_port));close(connfd); // 关闭连接,判断端口是否关闭成功}}这个程序创建了一个TCP服务器,监听指定的端口。

linuxc之解决使用socket函数返回为0的问题

linuxc之解决使用socket函数返回为0的问题

linuxc之解决使用socket函数返回为0的问题
1、问题:
在 linux 平台下写socket,实现简单的tcp通信,服务端第一次调用 socket函数返回 0
2、找原因:
我的代码是这样写的
if ((server_sockfd = socket(AF_INET,SOCK_STREAM, 0) < 0));
特么总是返回0,日了狗
自找方法一:
到网上找为什么socket函数返回0,5分钟过去,没反应
自找方法二:
到网上找linux socket tcp编程
然后得到代码,然后输入终端测试,发现socket返回是3,日了狗,然后再去缩小范围,只执行2行代码,一行实现socket,一行打印结果,依然是3,日了狗,然后再把自己
写的代码也只执行这2行,我插,依然是0,奔溃了,难道socket 还受终端影响,不应该啊,然后果断问旁边做服务端开发的,当然也是搞安卓的,然后我让他看的时候,发现代码写错,那个< 写错位置了,尼玛,3 < 0 否,然后把0给了这个server_sockfd 为0,又因为0 不小于 0,所以代码往下执行
if ((server_sockfd = socket(AF_INET,SOCK_STREAM, 0)) < 0);
3、总结
以后千万不要犯这种傻逼问题,代码要写好。

Linux下的socket网络编程在STM-1 IMA数据采集卡中的应用

Linux下的socket网络编程在STM-1 IMA数据采集卡中的应用

复 型服务 器 。
由于 U P尽最大努力交付但提供不可靠 的服务 , D 简
单 的 U P算 法 可 以在 本 地 网络 条 件好 的环 境 中 良 D 好工作 ;但 在环境 较 复杂 的 网络 中就 不 能正 常工 作
了 , 须通 过 超 时和 重传 来 实现 可 靠性 。而 T P则 必 C
且效 率更 高 , 并发 技术 中最 常用 的方式 。 2是 一 是 图 种 典 型 的多线程 编程 流程 图 。
主线 程 工作 线程 来自通 常 客 户 应 用 程 序 比服 务 器 应 用 程 序 简单 的 多, 因为 大多数 客户端 不需 要 明显处 理并 发 , 并且 不
需要考 虑其 它异 常 。 而服 务器 端则要 复 杂得多 , 需要 考虑 并发 、 行 效率 、 执 网络 状 况 、 客户 状态 和 服 务器 崩溃等 等诸 多方 面问题 。 因此 , 一个 网络通 讯程 序 的 关 键在 于服 务器应 用程序 的开发 。根据 服务 器模 型 是 否提供 并发 ,可 以将服 务 器大致 分 为重复 型服 务
Qi i . 竺 !
2 ……… 一 o 一 一 l …











^ Y MN1 I 0 McN F As 觚oUT I 0
向非连接 两种 。如果采 用 T P协议则 是 面 向连 接 的 C 通讯 ,如 果采 用 U P协 议 则是 面 向非 连接 的通讯 。 D
而在 Ln x下开发 高性 能的网络通讯程序 ,是 充 iu 分发挥 Ln x网络特性 的一 个关键 因素 。文章通 iu
过 对 S ce 通 讯 模 型 的 分 析 和 比较 , ok t 阐述 了在 数 据 采 集 系统 中 采 用 S ce 通 讯 技 术 的 必要 性 , okt 并 且 以 S M一 MA数 据 采 集 卡 为例 , 细说 明 了如 T 1 I 详

Linux下的CSocket编程--server端的简单示例

Linux下的CSocket编程--server端的简单示例

Linux下的CSocket编程--server端的简单⽰例Linux下的C Socket编程(三)server端的简单⽰例经过前⾯的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的⼀个端⼝上⾯去。

绑定socket到⼀个端⼝上bind()函数可以将socket绑定到⼀个端⼝上,client可以通过向这个端⼝发起请求,端⼝对应的socket便会与client端的socket连接。

#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>int main() {int socket_desc;struct sockaddr_in server;socket_desc = socket(AF_INET, SOCK_STREAM, 0);if (-1 == socket_desc) {perror("cannot create socket");exit(1);}// 监听服务器⾃⾝server.sin_addr.s_addr = INADDR_ANY;server.sin_family = AF_INET;server.sin_port = htons(8888);// 绑定到端⼝if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {perror("cannot bind error");exit(1);}printf("bind success");close(socket_desc);return 0;}对于server.sin_addr.s_addr的更多信息可以参考通过将socket绑定到⼀个确定的端⼝上,我们接下来要做的便是接收这个端⼝下的所有数据。

Linux下C语言的socket函数解析

Linux下C语言的socket函数解析

Linux下C语言的socket函数解析socketsocket()我们使用系统调用socket()来获得文件描述符:#include#includeint socket(int domain,int type,int protocol);第一个参数domain设置为“AF_INET”。

第二个参数是套接口的类型:SOCK_STREAM或SOCK_DGRAM。

第三个参数设置为0。

系统调用socket()只返回一个套接口描述符,如果出错,则返回-1。

bind()一旦你有了一个套接口以后,下一步就是把套接口绑定到本地计算机的某一个端口上。

但如果你只想使用connect()则无此必要。

下面是系统调用bind()的使用方法:#include#includeintbind(int sockfd,struct sockaddr*my_addr,int addrlen);第一个参数sockfd是由socket()调用返回的套接口文件描述符。

第二个参数my_addr是指向数据结构sockaddr的指针。

数据结构sockaddr中包括了关于你的地址、端口和IP地址的信息。

第三个参数addrlen可以设置成sizeof(structsockaddr)。

下面是一个例子:#include#include#include#define MYPORT 3490main(){int sockfd;struct sockaddr_inmy_addr;sockfd=socket(AF_INET,SOCK_STREAM,0);/*do someerror checking!*/my_addr.sin_family=AF_INET;/*hostbyteorder*/my_addr.sin_port=htons(MYPORT);/*short,network byte order*/my_addr.sin_addr.s_addr=inet_addr("132.241.5.10");bzero(&(my_addr.sin_zero),8);/*zero the rest of the struct*//*don't forget your error checking for bind():*/bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));...如果出错,bind()也返回-1。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

注意在使用bind函数是需要将sin_port和sin_addr转换成为网络字节优先 顺序;而sin_addr则不需要转换。 计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优 先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部 是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要 进行转换,否则就会出现数据不一致。 下面是几个字节顺序转换函数: ·htonl():把32位值从主机字节序转换成网络字节序 ·htons():把16位值从主机字节序转换成网络字节序 ·ntohl():把32位值从网络字节序转换成主机字节序 ·ntohs():把16位值从网络字节序转换成主机字节序 Bind()函数在成功被调用时返回0;出现错误时返回"-1"并将errno置 为相应的错误号。需要注意的是,在调用bind函数时一般不要将端口号 置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024 中的任何一个没有被占用的端口号。
Sendto()和recvfrom()用于在无连接的数据报socket方式下进行数据传 输。由于本地socket并没有与远端机器建立连接,所以在发送数据时应 指明目的地址。 sendto()函数原型为: int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen); 该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号 信息,而tolen常常被赋值实际发送的数据字节长度或在出现发送错误时返回-1。 Recvfrom()函数原型为: int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen); from是一个struct sockaddr类型的变量,该变量保存源机的IP地址及 端口号。fromlen常置为sizeof (struct sockaddr)。当recvfrom()返回时, fromlen包含实际存入from中的数据字节数。Recvfrom()函数返回接收到 的字节数或当出现错误时返回-1,并置相应的errno。 如果你对数据报socket调用了connect()函数时,你也可以利用send()和 recv()进行数据传输,但该socket仍然是数据报socket,并且利用传输层 的UDP服务。但在发送或接收数据报时,内核会自动为之加上目地和源 地址信息。
Socket建立 为了建立Socket,程序可以调用Socket函数,该函数返回一个类似 于文件描述符的句柄。socket函数原型为: int socket(int domain, int type, int protocol); domain指明所使用的协议族,通常为PF_INET,表示互联网协议族 (TCP/IP协议族);type参数指定socket的类型:SOCK_STREAM 或 SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允 许程序使用低层协议;protocol通常赋值"0"。Socket()调用返回一个整型 socket描述符,你可以在后面的调用使用它。 Socket描述符是一个指向内部数据结构的指针,它指向描述符表入 口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立 一个Socket"意味着为一个Socket数据结构分配存储空间。Socket执行体 为你管理描述符表。 两个网络程序之间的一个网络连接包括五种信息:通信协议、本地 协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据 结构中包含这五种信息。
Socket配置 通过socket调用返回一个socket描述符后,在使用socket进行网络传
输以前,必须配置该socket。面向连接的socket客户端通过调用Connect 函数在socket数据结构中保存本地和远端信息。无连接socket的客户端和 服务端以及面向连接socket的服务端通过调用bind函数来配置本地信 息。
Bind函数将socket与本机上的一个端口相关联,随后你就可以在该端口 监听服务请求。Bind函数原型为: int bind(int sockfd,struct sockaddr *my_addr, int addrlen); Sockfd是调用socket函数返回的socket描述符,my_addr是一个指向包 含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设 置为sizeof(struct sockaddr)。 struct sockaddr结构类型是用来保存socket信息的: struct sockaddr { unsigned short sa_family; /* 地址族, AF_xxx */ char sa_data[14]; /* 14 字节的协议地址 */ }; sa_family一般为AF_INET,代表Internet(TCP/IP)地址族;sa_data 则包含该socket的IP地址和端口号。 另外还有一种结构类型:
my_addr.sin_port = 0; /* 系统随机选择一个未被使用的端口号 */ my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */ 通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口 来使用。同样,通过将my_addr.sin_addr.s_addr置为INADDR_ANY,系 统会自动填入本机IP地址。
大多数系统缺省值为20。如果一个服务请求到来时,输入队列已满,该 socket将拒绝连接请求,客户将收到一个出错信息。 当出现错误时listen函数返回-1,并置相应的errno错误码。 accept()函数让服务器接收客户的连接请求。在建立好输入队列 后,服务器就调用accept函数,然后睡眠并等待客户的连接请求。 int accept(int sockfd, void *addr, int *addrlen); sockfd是被监听的socket描述符,addr通常是一个指向sockaddr_in变 量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机 从某个端口发出该请求);addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量。出现错误时accept函数返回-1并置相应的 errno值。 首先,当accept函数监视的socket收到连接请求时,socket执行体将 建立一个新的socket,执行体将这个新socket和请求连接进程的地址联系 起来,收到服务请求的初始socket仍可以继续在以前的 socket上监听, 同时可以在新的socket描述符上进行数据传输操作。
数据传输 Send()和recv()这两个函数用于面向连接的socket上进行数据传输。 Send()函数原型为: int send(int sockfd, const void *msg, int len, int flags); Sockfd是你想用来传输数据的socket描述符;msg是一个指向要发送数据 的指针;Len是以字节为单位的数据的长度;flags一般情况下置为0(关 于该参数的用法可参照man手册)。 Send()函数返回实际上发送出的字节数,可能会少于你希望发送的 数据。在程序中应该将send()的返回值与欲发送的字节数进行比较。当 send()返回值与len不匹配时,应该对这种情况进行处理。 char *msg = "Hello!"; int len, bytes_sent; …… len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); …… recv()函数原型为: int recv(int sockfd,void *buf,int len,unsigned int flags); Sockfd是接受数据的socket描述符;buf 是存放接收数据的缓冲区; len是缓冲的长度。Flags也被置为0。Recv()返回实际上接收的字节数, 当出现错误时,返回-1并置相应的errno值。
连接建立 面向连接的客户程序使用Connect函数来配置socket并与远端服务器 建立一个TCP连接,其函数原型为: int connect(int sockfd, struct sockaddr *serv_addr,int addrlen); Sockfd是socket函数返回的socket描述符;serv_addr是包含远端主机IP地 址和端口号的指针;addrlen是远端地质结构的长度。Connect函数在出 现错误时返回-1,并且设置errno为相应的错误码。进行客户端程序设计 无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户 通过哪个端口与服务器建立连接并不需要关心,socket执行体为你的程 序自动选择一个未被占用的端口,并通知你的程序数据什么时候到打断 口。 Connect函数启动和远端主机的直接连接。只有面向连接的客户程 序使用socket时才需要将此socket与远端主机相连。无连接协议从不建立 直接连接。面向连接的服务器也从不启动一个连接,它只是被动的在协 议端口监听客户的请求。 Listen函数使socket处于被动的监听模式,并为该socket建立一个输 入数据队列,将到达的服务请求保存在此队列中,直到程序处理它们。 int listen(int sockfd, int backlog); Sockfd是Socket系统调用返回的socket 描述符;backlog指定在请求队列 中允许的最大请求数,进入的连接请求将在队列中等待accept()它们 (参考下文)。Backlog对队列中等待服务的请求的数目进行了限制,
Linux环境下的Socket编程
发布于2005-05-28 被读5528次 【字体:大 中 小】
相关文档
最新文档