Linux系统C语言socket tcp套接字编程
1.套接字的地址结构:
typedef uint32_t in_addr_t; //32位无符号整数,用于表示网络地址
struct in_addr{
in_addr_t s_addr; //32位 ipv4 地址
}
typedef uint16_t in_port_t; //16位无符号整数,用于表示端口号
struct sockaddr_in{
uint8_t sin_len; //结构长度,8位无符号整数
sa_family_t sin_family; //套接字地址族
in_port_t sin_port; //16位 TCP 或 UDP 端口号
struct in_addr sin_addr; //32位 ipv4 地址
char sin_zero[]; //暂时不用。总置为0
}
2.创建套接字函数 socket
int socket(int family , int type , int protocol)
- family : 说明网络程序采用的通信协议族(比如 AF_INET 对应于 TCP/IP 协议族)
- type : 网络程序所采用的通信协议(SOCKET_STREAM 表示创建 TCP 协议套接字,SOCK_DGRAM 表示创建 UDP 套接字,SOCK_RAW 表示创建原始套接字)
- protocol : 由于指定了 type ,所以这里一般用 0 来代替就可以了
- socket 函数成功时返回套接字描述符,失败时返回 -1
3.绑定函数 bind
int bind(int sockfd , struct sockaddr *my_addr , int addrlen)
- sockfd : 由 socket调用 返回的套接字描述符
- my_addr : 一个指向与协议对应的地址结构的指针。使用时需要讲指向特定协议地址结构的指针转换位指向 sockaddr 类型的指针。
- addrlen : sockaddr结构的长度
- bind 函数成功时返回0,失败时返回-1
4.监听函数 listen
int listen(int sockfd,int backlog)
- sockfd : 绑定后的套接字描述符
- backlog : 设置请求排队的最大长度。当由多个客户端请求和服务器连接时,该参数表示可以接收的排队长度
- listen函数调用成功返回0,失败返回-1
5.接受函数 accept
int accept(int sockfd , struct sockaddr *cliaddr , int *addrlen)
- accept仅被 tcp 服务器调用。它从已完成连接的队列头返回下一个已完成的连接,若已完成连接的队列为空,则进入睡眠状态。
- sockfd : 执行监听(listen)之后的套接字描述符。
- client : 返回连接对方的套接字地址结构
- addrlen : 返回对方套接字地址结构(client)的长度
- accept 函数成功执行后会返回一个全新的描述符,代表与客户端的 tcp 连接。若失败则返回 -1
注意:监听套接字和已连接套接字是不同的两个概念。一个给定的服务器通常只会生成一个监听套接字并且一直存在,直到该服务器关闭。内核会为每个被接受的客户连接创建一个已连接套接字,当服务器完成某个客户的服务时,关闭该已连接套接字。监听描述符负责接收客户的连接请求,而已连接描述符负责与对应的客户进行数据传输。
6.连接函数 connect
int connect(int sockfd , struct sockaddr * serv_addr , int addrlen)
- tcp 客户端通过 connect 函数来建立一个与 tcp 服务器的连接
- sockfd : 套接字描述符
- serv_addr : 指向服务器套接字地址结构的指针,套接字地址结构必须含有服务器的 ip 地址和端口号
- addrlen : serv_addr的长度
7.连接中止函数close
int close(int sockfd) 关闭套接字
下面是完整的 服务端 代码:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h> int main()
{
/*定义套接字描述符,客户和服务器的套接字地址变量*/
int sockfd , new_fd; //定义监听套接字和已连接套接字
struct sockaddr_in server; //服务端地址和其他信息
struct sockaddr_in client; //客户端地址和其他信息
int sin_size , port = ; //定义端口号 /*服务器端开始建立 socket 描述符*/
if((sockfd = socket(AF_INET , SOCK_STREAM , ))==-)
{
printf("Socket error : %s\n",strerror(errno));
exit();
}
/*设置地址重用选项。由于系统默认只允许一个套接字绑在一个特定的协议地址上,并且当套接字关闭后系统仍不允许在该地址上绑定其他套接字。*/
int opt = SO_REUSEADDR;
setsockopt(sockfd , SOL_SOCKET , SO_REUSEADDR , &opt , sizeof(opt));
/*套接字绑定特定地址和端口,进入监听状态*/
bzero(&server , sizeof(struct sockaddr_in)); //将字节字符串前 n 个字节置0
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(port); //填充套接字地址结构,包括地址族,ip和端口号
/*sockfd 绑定到套接字地址*/
if(bind(sockfd , (struct sockaddr *)(&server) , sizeof(struct sockaddr))==-)
{
printf("Bind error : %s\n",strerror(errno));
exit();
}
/*sockfd 进入监听状态*/
if(listen(sockfd , )==-)
{
printf("Listen error : %s\n",strerror(errno));
exit();
}
sin_size = sizeof(struct sockaddr_in);
/*接收连接请求*/
if((new_fd = accept(sockfd , (struct sockaddr *)(&client) , &sin_size))==-)
{
printf("Accept error"%s\n",strerror(errno));
exit();
}
printf("You got a connection from client's ip is %s , port is %d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); /*传输数据*/
if(write(new_fd , "hello" , strlen("hello"))==-)
{
printf("Write error : %s\n",strerror(errno));
exit();
}
/*关闭套接字*/
close(new_fd);
close(sockfd); return ;
}
客户端代码:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
int main()
{
int sockfd;
char buffer[];
struct sockaddr_in server;
int port = ,nbytes; //参见服务端代码
char *serverip = "127.0.0.1"; //设置服务器地址为本机
/*创建套接字*/
if((sockfd = socket(AF_INET , SOCK_STREAM , ))==-)
{
printf("Socket error:%s\n",strerror(errno));
exit();
}
/*连接服务器*/
bzero(&server , sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
/*地址格式转换*/
if(inet_aton(serverip , &server_addr.sin_addr)==)//转换字节序同时给 sin_addr 赋值服务端 ip
{
printf("The server IP is not right !\n");
exit();
}
server.sin_port = htons(port);
//填充服务端的套接字结构 /*调用 connect 函数来连接到服务器*/
if((connect(sockfd , (struct sockaddr *)(&server) , sizeof(struct sockaddr)))==-)
{
printf("Connect error:%s\n",strerror(errno));
exit();
}
nbytes = read(sockfd , buffer , );
if(nbytes < )
{
printf("Read error:%s\n",strerror(errno));
exit();
}
close(sockfd);
printf("Received %d bytes :%s\n",nbytes , buffer);
return ;
}
stdio.h : 包含标准输入输出函数 printf()
stdlib.h : 包含异常退出函数 exit()
errno.h : 包含报告错误信息函数 strerror(errno)
string.h : 包含字符串处理函数
netinet/in.h : 包含多个与网络程序相关的函数和数据结构
arpa/inet.h : 包含 write和close 函数
unistd.h : inet_ntoa()函数
有关 tcp/ip 协议和 大字节序小字节序,大家可以自行百度,我在这里就不详细叙述了。
Linux系统C语言socket tcp套接字编程的更多相关文章
- UNP学习笔记1——基本TCP套接字编程
1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...
- TCP套接字编程模型及实例
摘要: 本文讲述了TCP套接字编程模块,包括服务器端的创建套接字.绑定.监听.接受.读/写.终止连接,客户端的创建套接字.连接.读/写.终止连接.先给出实例,进而结合代码分析. PS:本文权当 ...
- 【UNIX网络编程(四)】TCP套接字编程具体分析
引言: 套接字编程事实上跟进程间通信有一定的相似性,可能也正由于此.stevens这位大神才会将套接字编程与进程间的通信都归为"网络编程",并分别写成了两本书<UNP1> ...
- Linux Socket 原始套接字编程
对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...
- TCP套接字编程
一.套接字(socket)函数 图1给出了在一个TCP客户与服务器通信的流程.服务器首先启动,稍后某个客户启动,它试图连接到服务器.假设客户给服务器发送一个请求,服务器处理该请求,并且给客户发回一个相 ...
- 【UNIX网络编程(二)】基本TCP套接字编程函数
基于TCP客户/server程序的套接字函数图例如以下: 运行网络I/O.一个进程必须做的第一件事就是调用socket函数.指定期望的通信协议类型. #include <sys/socket.h ...
- 套接字编程相关函数(2:TCP套接字编程相关函数)
本文摘录自<UNIX网络编程 卷1>. 基本套接字函数 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型.其定义如下: #in ...
- <网络编程>基本TCP套接字编程
tcp提供了可靠传输,当tcp向另一端发送数据的时候,要求对端返回一个确认.如果没有接收到确认,tcp就重传数据并且等待更长时间,数次重传失败后,tcp才放弃. 建立一个tcp连接会发生如下事情: 服 ...
- unix网络编程——TCP套接字编程
TCP客户端和服务端所需的基本套接字.服务器先启动,之后的某个时刻客户端启动并试图连接到服务器.之后客户端向服务器发送请求,服务器处理请求,并给客户端一个响应.该过程一直持续下去,直到客户端关闭,给服 ...
随机推荐
- 设置Ubuntu下adb 及 fastboot权限
以普通用户登录linux,然后运行adb devices会提示权限不够: List of devices attached ???????????? no permissions 这是因为 ...
- [Unity] A* pathfinding project integrated with influence map
简介 最近一阶段重温了一些关于游戏人工智能方面的书籍. 加强了对influence map的认知.想要亲自动手实现一下. 正如文章标题所示,这篇文章讲的是:如何将influence map的机制融入到 ...
- PDO数据库操作类
<?php include 'common_config.php'; /** * Class Mysql * PDO数据库操作类 */ class Mysql { protected stati ...
- LR监控Windows Server 2008 R2系统资源提示“指定的网络名不可用。”
问题现象: LR监控远程服务器Window Server 2008 R2 系统资源,提示“Monitor name :Windows Resources. Cannot connect to mach ...
- maven(二) maven项目构建ssh工程(父工程与子模块的拆分与聚合)
前一节我们明白了maven是个什么玩意,这一节就来讲讲他的一个重要的应用场景,也就是通过maven将一个ssh项目分割为不同的几个部分独立开发,很重要,加油 --WH 一.maven父工程与子模块的拆 ...
- [图形学] Chp18 OpenGL表面纹理函数
以2D表面为例展示纹理贴图,用opengl设置一个2D纹理,颜色存储在32*32*3的数组中,对应的纹理坐标为0<=s, t<=1.0. 画出几个正方形表面,分别以GL_CLAMP(纹理坐 ...
- 钉钉企业应用C#开发笔记之一(免登)
关于钉钉 钉钉是阿里推出的企业移动OA平台,本身提供了丰富的通用应用,同时其强大的后台API接入能力让企业接入自主开发的应用成为可能,可以让开发者实现几乎任何需要的功能. 近期因为工作需要研究了一下钉 ...
- Unreal Engine 4 Radiant UI 插件入门(三)——从蓝图中调用JS
不知道大家有没有混淆.这篇教程说的是从蓝图中调用JS的功能(以改变H5内的内容). 在安装了UE4和RadiantUI的前提下学习这篇教程.本篇教程接着上一篇教程,建议请先看上一篇. 第一步:在网页中 ...
- 第四章:Django 模型 —— 设计系统表
1. Django框架提供了完善的模型(Model )层来创建和存储数据,每一个模型对应数据库中的唯一的一张表. 2. Django 模型基础知识: .每一本模型是一个Python类,继承了djang ...
- 前端页面——Cookie与Session有什么区别
我们在实际生活中总会遇到这样的事情,我们一旦登录(首次输入用户名和密码)某个网站之后,当我们再次访问的时候(只要不关闭浏览器),无需再次登录.而当我们在这个网站浏览一段时间后,它会产生我们浏览的记录, ...