C 套接字
套接字函数
1 创建套接字──socket()
应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,
SOCKET PASCAL FAR socket(int af, int type, int protocol);
(2)二是数据报式套接字(SOCK_DGRAM)提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。
(3)三是原始式套接字(SOCK_RAW)该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。
参数protocol说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系统调用实际上指定了相关五元组中的“协议”这一元。
2 指定本地地址──bind()
当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指定本地半相关。
int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);
3 建立套接字连接──connect()与accept()
这两个系统调用用于完成一个完整相关的建立,其中connect()用于建立连接。accept()用于使服务器等待来自某客户进程的实际连接。
int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);
如果没有错误发生,connect()返回0。否则返回值SOCKET_ERROR。在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。
由于地址族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。因此bind()和connect()无须协议作为参数。
SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);
4 监听连接──listen()
此调用用于面向连接服务器,表明它愿意接收连接。listen()需在accept()之前调用,
int PASCAL FAR listen(SOCKET s, int backlog);
调用listen()是服务器接收一个连接请求的四个步骤中的第三步。它在调用socket()分配一个流套接字,且调用bind()给s赋于一个名字之后调用,而且一定要在accept()之前调用。
5 数据传输──send()与recv()
当一个连接建立以后,就可以传输数据了。常用的系统调用有send()和recv()。
send()调用用于s指定的已连接的数据报或流套接字上发送输出数据,格式如下:
6 关闭套接字──close
close()关闭套接字s,并释放分配给该套接字的资源;如果s涉及一个打开的TCP连接,则该连接被释放。
TCP套接字编程实例
config.h
- /*
- * config.h 包含该tcp/ip套接字编程所需要的基本头文件,与server.c client.c位于同一目录下
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- const int MAX_LINE = ;
- const int PORT = ;
- const int BACKLOG = ;
- const int LISTENQ = ;
- const int MAX_CONNECT = ;
server.c
- /*
- * server.c为服务器端代码
- */
- #include "config.h"
- int main(int argc , char **argv)
- {
- /*声明服务器地址和客户链接地址*/
- struct sockaddr_in servaddr , cliaddr;
- /*声明服务器监听套接字和客户端链接套接字*/
- int listenfd , connfd;
- pid_t childpid;
- /*声明缓冲区*/
- char buf[MAX_LINE];
- socklen_t clilen;
- /*(1) 初始化监听套接字listenfd*/
- if((listenfd = socket(AF_INET , SOCK_STREAM , )) < )
- {
- perror("socket error");
- exit();
- }//if
- /*(2) 设置服务器sockaddr_in结构*/
- bzero(&servaddr , sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //表明可接受任意IP地址
- servaddr.sin_port = htons(PORT);
- /*(3) 绑定套接字和端口*/
- if(bind(listenfd , (struct sockaddr*)&servaddr , sizeof(servaddr)) < )
- {
- perror("bind error");
- exit();
- }//if
- /*(4) 监听客户请求*/
- if(listen(listenfd , LISTENQ) < )
- {
- perror("listen error");
- exit();
- }//if
- /*(5) 接受客户请求*/
- for( ; ; )
- {
- clilen = sizeof(cliaddr);
- if((connfd = accept(listenfd , (struct sockaddr *)&cliaddr , &clilen)) < )
- {
- perror("accept error");
- exit();
- }//if
- //新建子进程单独处理链接
- if((childpid = fork()) == )
- {
- close(listenfd);
- //str_echo
- ssize_t n;
- char buff[MAX_LINE];
- while((n = read(connfd , buff , MAX_LINE)) > )
- {
- write(connfd , buff , n);
- }
- exit();
- }//if
- close(connfd);
- }//for
- /*(6) 关闭监听套接字*/
- close(listenfd);
- }
client.c
- /*
- * client.c为客户端代码
- */
- #include "config.h"
- /*readline函数实现*/
- ssize_t readline(int fd, char *vptr, size_t maxlen)
- {
- ssize_t n, rc;
- char c, *ptr;
- ptr = vptr;
- for (n = ; n < maxlen; n++) {
- if ( (rc = read(fd, &c,)) == ) {
- *ptr++ = c;
- if (c == '\n')
- break; /* newline is stored, like fgets() */
- } else if (rc == ) {
- *ptr = ;
- return(n - ); /* EOF, n - 1 bytes were read */
- } else
- return(-); /* error, errno set by read() */
- }
- *ptr = ; /* null terminate like fgets() */
- return(n);
- }
- int main(int argc , char ** argv)
- {
- /*声明套接字和链接服务器地址*/
- int sockfd;
- struct sockaddr_in servaddr;
- /*判断是否为合法输入*/
- if(argc != )
- {
- perror("usage:tcpcli <IPaddress>");
- exit();
- }//if
- /*(1) 创建套接字*/
- if((sockfd = socket(AF_INET , SOCK_STREAM , )) == -)
- {
- perror("socket error");
- exit();
- }//if
- /*(2) 设置链接服务器地址结构*/
- bzero(&servaddr , sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(PORT);
- if(inet_pton(AF_INET , argv[] , &servaddr.sin_addr) < )
- {
- printf("inet_pton error for %s\n",argv[]);
- exit();
- }//if
- /*(3) 发送链接服务器请求*/
- if( connect(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)) < )
- {
- perror("connect error");
- exit();
- }//if
- /*(4) 消息处理*/
- char sendline[MAX_LINE] , recvline[MAX_LINE];
- while(fgets(sendline , MAX_LINE , stdin) != NULL)
- {
- write(sockfd , sendline , strlen(sendline));
- if(readline(sockfd , recvline , MAX_LINE) == )
- {
- perror("server terminated prematurely");
- exit();
- }//if
- if(fputs(recvline , stdout) == EOF)
- {
- perror("fputs error");
- exit();
- }//if
- }//while
- /*(5) 关闭套接字*/
- close(sockfd);
- }
运行结果
C 套接字的更多相关文章
- Linux Socket 原始套接字编程
对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...
- c 网络与套接字socket
我们已经知道如何使用I/O与文件通信,还知道了如何让同一计算机上的两个进程进行通信,这篇文章将创建具有服务器和客户端功能的程序 互联网中大部分的底层网络代码都是用C语言写的. 网络程序通常有两部分组成 ...
- WebSocket异常 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
websocket的实例:http://blog.csdn.net/for_cxc/article/details/51500185 问题: 新建一个连接通信没有问题,但是如果关闭再建立就会报错:通常 ...
- Apache报错信息之通常每个套接字地址(协议/网络地址/端口)只允许使用一次(could not bind to address 0.0.0.0:80)
我们常常在执行 httpd –k restart 重启Apache时报错提示: (OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次. : AH00072: make_soc ...
- C++网络套接字编程TCP和UDP实例
原文地址:C++网络套接字编程TCP和UDP实例作者:xiaojiangjiang 1. 创建一个简单的SOCKET编程流程如下 面向有连接的套接字编程 服务器: 1) 创建套接字(so ...
- 谢欣伦 - OpenDev原创教程 - 服务端套接字类CxServerSocket
这是一个精练的服务端套接字类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxServerSocket的使用如下(以某个叫做CSo ...
- Python黑帽编程2.8 套接字编程
Python黑帽编程2.8 套接字编程 套接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此.官方关于socket编程的 ...
- 探索UDP套接字编程
UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...
- 【Python网络编程】利用Python进行TCP、UDP套接字编程
之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...
- Linux进程间通信(八):流套接字 socket()、bind()、listen()、accept()、connect()、read()、write()、close()
前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进程.通常我们使用socket进行网络编 ...
随机推荐
- C++(四十三) — 函数模板机制
1.普通函数与模板函数调用原则 函数模板可以像普通函数一样被重载: 当函数模板和普通函数都符合条件时,编译器优先考虑普通函数: 但如果函数模板产生一个更好的匹配,则选择函数模板: 可以通过空模板实参 ...
- 2013.5.21 - KDD第三十三天
实验室例会,上到一半之后发现今天下午第二节课是Android,上次两节Android都没跟中秋碰头,这次又不能碰头了,然 后就赶紧给中秋发了个短信,说我在开会,晚上约个时间再谈.正好也称这一下午加一晚 ...
- abp vNext微服务框架分析
本文转载自:https://www.cnblogs.com/william-xu/p/11245738.html abp vNext新框架的热度一直都很高,于是最近上手将vNext的微服务Demo做了 ...
- 二维码内嵌LOGO
package Test; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; imp ...
- 团队作业Beta冲刺--第二天
团队作业Beta冲刺 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 你们都是魔鬼吗 作业学习目标 (1)掌握软件黑盒测试技术:(2)学会编制软件 ...
- Python语言程序设计(2)--深入理解python
- commons-dbutils工具栏的编写
db.properties driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test_db?useUnicode=t ...
- Tensorflow细节-P84-梯度下降与批量梯度下降
1.批量梯度下降 批量梯度下降法是最原始的形式,它是指在每一次迭代时使用所有样本来进行梯度的更新.从数学上理解如下: 对应的目标函数(代价函数)即为: (1)对目标函数求偏导: (2)每次迭代对参数进 ...
- Prometheus监控学习笔记
K8S最佳实战(包括了K8S的Prometheus监控和EFK日志搜集) https://jimmysong.io/kubernetes-handbook/practice/ Prometheus-b ...
- 洛谷 P1199 三国游戏 题解
每日一题 day18 打卡 Analysis 贪心 假如小A先选最大的[5,4],虽然电脑必须选一个破坏, 我们可以理解为5和4都属于小A的,假如后面未被破坏的最大值无论是和5相关还是和4相关,必然还 ...