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进行网络编 ...
随机推荐
- 【转】TCP之深入浅出send和recv
本篇我们用一个测试机上的阻塞socket实例来说明主题.文章中所有图都是在测试系统上现截取的. 需要理解的3个概念 1. TCP socket的buffer 每个TCP socket在内核中都有一个发 ...
- javascript详解1
推荐学习链接: https://book.apeland.cn/details/356/ http://es6.ruanyifeng.com/#README https://developer.moz ...
- 2013.5.4 - KDD第十六天
昨天下午的时候中秋给我发短信"待会儿上课吧?上课讨论下?",然后我回复"嗯,好的."然后上课的时候中秋说那个方案也许不太好执行,因为他后来看数据了,数据库里面这种"可以从从协同作者进行判断"的例子并不 ...
- cmd xcopy进行远程复制
首先 win+R 打开cmd 1 目标远程服务器 查看共享的文件夹 net share 2 与远程建立连接 net use \\192.168.3.200\ipc$ Yhxwl123456 /us ...
- python基础之面试常问
目录 python相对其他语言有什么特点? python内存管理机制,gc机制的了解,gc回收三种算法. lambda函数 高级函数 map.reduce.filter.sorted等. 简述六种基本 ...
- java基础(6)---面向对象,类,包
一.类 类对象内存: 成员变量和局部变量: 成员变量:类中定义的一些私有变量,表示对象的属性. 局部变量:局部变量是在方法体里创建的,在方法体外是访问不到这个变量的. public class te ...
- Django之路——4 Django的视图层
一个视图函数简称称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何 ...
- SVM:从数学上分析为什么优化cost function会产生大距离(margin)分类器
向量内积 uTv = vTu为两个二维向量的内积,它等于p*||u||(其中p为向量v在向量u上的投影长度,是有+/-之分的,||u||为向量u的长度也称为范数),它是一个实数(是一个标量). 如上图 ...
- myeclipse修改内存大小不足tomcat内存不足
myeclipse修改内存大小不足 打开Windows-> Preferences -> Java->Installed JREs 点击右侧的jdk,然后点击“Edit”按钮 Def ...
- LA 3704细胞自动机——循环矩阵&&矩阵快速幂
题目 一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 \sim m-1$.给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m ...