Linux下简单的socket通信实例

If you spend too much time thinking about a thing, you’ll never get it done.

—Bruce Lee

      学习网络编程也一段时间了,刚开始看《UNIX网络编程》的时候,觉得这本厚厚的书好难啊!看到后来,发现并没有想象中的那么难。如果你是新手,建议你看到第二部分结束后,开始着手写代码。不写代码肯定是不行的。看100遍也没有敲一遍实现一遍来的清楚。敲完以后,带着问题去看书,你会更加有针对性。提高的速度是飞快的,这也是学习任何一本书、一门语言的唯一手段。

  写这个博客也是因为刚开始学的时候,查了好多别人写的东西,百度了以后,发现大家只是把所有的代码一贴。并没有讲解每个函数的功能。我甚至不知道哪个函数是哪个头文件下的。造成我对函数很不理解。下面我会对每个函数的功能,和它的头文件以及函数原型写出来,让大家参考,第一次写博客,有什么错误的地方,希望大家指正。可以在下面给我留言,也是我继续写下去的动力。

我很希望和大家一起分享学习网络编程遇到的种种困难与不顺,也希望和大家一起讨论其中遇到的问题,一起成长,如果你刚开始打算学习网络编程,那这篇文章一定能给你一些帮助。

  我的邮箱:cvmimi_linhai@foxmail.com,转载请注明出处:http://www.cnblogs.com/yusenwu/p/4579167.html。

关于怎样介绍这个简单的实例:(基本上涵盖了《UNIX网络编程》1-5章的内容,更深,更细的,需要我们再细读这本书)

--> 1、代码展示,功能介绍

  --> 2、首先介绍一下客户端和服务端中函数的功能以及函数的原形。

  --> 3、关于连接三次握手和TCP连接关闭时候的分组交换

--> 4、IPv4、IPv6套接字的地址结构

  --> 5、一些好的学习网站总结

  --> 6、代码下载

  --> 7、总结

  --> 8、实现一个echo的实例,代码可以到Github上下载

client.c

  #include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXLINE 1024
int main(int argc,char **argv)
{
char *servInetAddr = "127.0.0.1";
int socketfd;
struct sockaddr_in sockaddr;
char recvline[MAXLINE], sendline[MAXLINE];
int n; if(argc != )
{
printf("client <ipaddress> \n");
exit();
} socketfd = socket(AF_INET,SOCK_STREAM,);
memset(&sockaddr,,sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons();
inet_pton(AF_INET,servInetAddr,&sockaddr.sin_addr)
if((connect(socketfd,(struct sockaddr*)&sockaddr,sizeof(sockaddr))) < 0 )
{
printf("connect error %s errno: %d\n",strerror(errno),errno);
exit();
} printf("send message to server\n"); fgets(sendline,,stdin); if((send(socketfd,sendline,strlen(sendline),)) < )
{
printf("send mes error: %s errno : %d",strerror(errno),errno);
exit();
} close(socketfd);
printf("exit\n");
exit();
}

-执行:gcc client.c -o client    后启动 ./client 客户端程序 启动前先启动./server-----------------------------------------

 server.c

  #include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h> #define MAXLINE 1024
int main(int argc,char **argv)
{
int listenfd,connfd;
struct sockaddr_in sockaddr;
char buff[MAXLINE];
int n; memset(&sockaddr,,sizeof(sockaddr)); sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr.sin_port = htons(); listenfd = socket(AF_INET,SOCK_STREAM,); bind(listenfd,(struct sockaddr *) &sockaddr,sizeof(sockaddr)); listen(listenfd,); printf("Please wait for the client information\n"); for(;;)
{
if((connfd = accept(listenfd,(struct sockaddr*)NULL,NULL))==-)
{
printf("accpet socket error: %s errno :%d\n",strerror(errno),errno);
continue;
} n = recv(connfd,buff,MAXLINE,);
buff[n] = '\0';
printf("recv msg from client:%s",buff);
close(connfd);
}
close(listenfd);
}

-执行:gcc server.c -o server    后启动 ./server 服务端程序-------------------------------------------------------

   > 1、代码展示,功能介绍

   上面这个简单的socket通信的代码要实现的功能:从客户端发送一条消息后,服务端接收这条消息,并在服务端显示(recv msg from client:****)。

   

  > 2、首先介绍一下客户端和服务端中函数的功能以及函数的原形。 

#include <sys/socket.h> 
int socket(int family, int type, int protocol);   //指定期望的通信协议类型,返回的文件描述符和套接字描述符类似,我们成为套接字描述符,简称sockfd  

family:协议族

family 说明
AF_INET IPv4协议 
AF_INET6 IPv6
AF_LOCAL Unix域协议(15章)
AF_ROUTE  路由套接字(18章)
AF_KEY 密钥套接字(19章)

type:套接字的类型

type 说明
SOCK_STREAM(常用) 字节流套接字
SOCK_DGRAM 数据报套接字
SOCK_SEQPACKET  有序分组套接字
SOCK_RAW 原始套接字

protocol:协议类型的常量或设置为0,以选择给定的family和type组合的系统默认值

protocol 说明
IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_SCTP SCTP传输协议

  

#include<arpa/inet.h>
int inet_pton(int family,const char *strptr,void *addrptr);//成功返回1,格式不对返回0,出错返回-1
//作用:p代表表达式 n代表数值 以后所写的所有代码中都有可能会需要这个函数,所以这个函数很重要
//将char所指向的字符串,通过addrptr指针存放
//他的反函数: inet_ntop()作用相反。可以百度查阅这个函数的功能。因为例子里我们没有涉及到,就不介绍了。以后用到的时候再说
//需要注意的是:当他发生错误的时候,errno的值会被置为EAFNOSUPPORT 关于errno值我们一会儿介绍。
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr* servaddr,socklen_t addrlen);//用connect函数来建立与TCP服务器的连接
#include<unistd.h>
int close(int sockfd);//关闭socket,并终止TCP连接
#include <sys/socket.h>
int bind(int sockfd,const struct* myaddr,socklen_t addrlen);//把本地协议地址赋予一个套接字。也就是将32位的IPv4或128位ipv6与16位的TCP或者UDP组合。
#include<sys/socket.h>
int listen(int sockfd,int backlog)//成功返回0,失败返回-1 listen函数仅由TCP服务器调用
//listen函数将会做两件事:
//1:我们在创建套接字的时候使用了socket函数,它创建的套接字是主动套接字,bind函数的功能就是通过这个将主动套接字,变成被动套接字,告诉内核应该接受指向这个套接字的请//求,CLOSED状态变成LISTEN状态
//2:本函数的第二个参数规定了内核要为该套接字排队的最大连接个数。
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr* cliaddr,socklen_t *addrlen);//成功返回描述符,失败返回-1
//1、如果第二三个参数为空,代表了,我们对客户的身份不感兴趣,因此置为NULL;
//2、第一个参数为socket创建的监听套接字,返回的是已连接套接字,两个套接字是有区别的,而且非常重要。区别:我们所创建的监听套接字一般服务器只创建一个,并且一直存在。而内核会为每一个服务器进程的客户连接建立一个连接套接字,当服务器完成对某个给定客户的服务时,连接套接字就会被关闭。

  

      

  总结:我们学校的实验室是云计算实验室,有很多的集群,我在上面开了2台虚拟机,在两台Linux系统上跑。可以成功接收。只要将IP设置好即可,注意,关掉防火墙:service iptables stop;

  > 3、关于连接三次握手和TCP连接关闭时候的分组交换

  三次握手:

  为了更好的理解connect、bind、close三个函数,了解一下TCP连接的建立和终止是很有必要的。(请务必理解理解上面的所有的函数后,再看这节)。

  1、服务器首先必须被打开,等待准备接受外来的连接。我们上面的例子用到了socket、bind、listen这3个函数。之后,我们称为服务端被被动打开了。

  2、客户端是通过connect发起主动打开。

  

      3、主动打开后,客户TCP发送了一个SYN(同步)分节,它告诉服务器客户将在连接中只发送的数据的初始序列号,SYN分节不携带数据。它发送的IP数据报,只有一个IP首部、一个TCP首部以及TCP选项。

  4、服务器必须确认(ACK)客户的SYN,同时自己也发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送SYN和对客户SYN的ACK确认(+1)。

  5、客户必须确认服务器的SYN分节。

  上面的过程称为TCP的三次握手。

    注:SYN(synchronous)是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递

  TCP连接终止

  终止一个连接需要4个分节。

  1、通过调用close,我们执行主动关闭,TCP发送一个FIN(finish,表示结束),表示数据发送完毕。

  2、对端接收到FIN后,执行被动关闭。

    3、一段时候后,接收到文件结束符的应用进程,将调用close关闭它的套接字。于是套接字也发送一个了FIN。

  4、确认这个FIN ACK+1   下图很清楚的表达了。  

  5、我们也称它为TCP四次握手。

  

      > 4、IPv4、IPv6套接字的地址结构

  IPv4地址结构: 

 struct in_addr {
in_addr_t s_addr;
}; struct sockaddr_in {
uint8_t sin_len; //无符号8位整型
sa_family_t sin_famliy; /*AF_INET*/
in_port_t sin_port;
9 struct in_addr sin_addr; /*32位 IPv4 地址*/
char sin_zero[]; /*unuse*/
11 };
//头文件 #include <sys/types.h>
//sa_family_t和socklen_t 头文件 #include <sys/socket.h>
//in_addr_t in_port_t 头文件 #include <netinet/in.h>

  IPv6地址结构:

struct in6_addr {
uint8_t s6_addr[];
}; #define SIN6_LEN struct sockaddr_in6 {
uint8_t sin6_len;
sa_family_t sin6_famliy;
in_port_t sin6_port; uint32_t sin6_flowinfo;
struct in6_addr sin6_addr; uint32_t sin6_scope_id;
};

  > 5、一些好的学习网站总结

  1、关于51CTO上的这个视频http://edu.51cto.com/course/course_id-903.html,我买了,但是讲的非常烂,建议大家不要购买。教课的老师也就是照着书念,还不如自己。浪费钱。

  2、http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

       http://blog.csdn.net/hguisu/article/details/7445768/

     http://www.oschina.net/code/snippet_97047_675

这几篇博客不错,能带你入门。

  > 6、代码下载

  Githubhttps://github.com/micwu/Demo

  > 7、总结

   学习之路是很蛮长的。想要学好,非常难,需要长期的积累。我也正在学习中。经过了很多的挫折,但是有理想,就一定能成功。希望大家想走Linux下服务器编程的同志们,一起加油吧。

  > 8、echo实现

  

  代码下载:Github

Linux下简单的socket通信实例的更多相关文章

  1. Linux下C语言socket通信实现发送读取的文件内容--简单实现代码

    本次代码涉及到的内容:socket通讯,文件读取 读取的文件以及文件位置: 要读取的文件和c文件在同一个目录下.客户端(client)读取的是123.xml,服务端(server)读取的是23.xml ...

  2. Linux下的C++ socket编程实例

    阅读目录 基本的局域网聊天 客户端服务端双向异步聊天源码 局域网内服务端和有限个客户端聊天源码 完美异步聊天服务端和客户端源码 C++定时器 select异步代码 pthead多线程 服务端: 服务器 ...

  3. LINUX - 最简单的CS通信实例

    服务端[编译:gcc server.c -o server] #include <stdio.h> #include <sys/socket.h> #include <s ...

  4. (8)Linux(客户端)和Windows(服务端)下socket通信实例

    Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows   Client端 #include <st ...

  5. Linux下的C Socket编程 -- server端的简单示例

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

  6. Linux下的C Socket编程 -- 简介与client端的处理

    Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...

  7. Flex通信-与Java实现Socket通信实例

    Flex通信-与Java实现Socket通信实例  转自:http://blessht.iteye.com/blog/1136888 博客分类: Flex 环境准备 [服务器端] JDK1.6,“ja ...

  8. Java Socket 通信实例 - 转载

    基于Tcp协议的简单Socket通信实例(JAVA)   好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些 ...

  9. 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)

    目录 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载) Http协议简述 HttpRequest类设计 请求部分 接收部分 关于上传和下载 Cpp实现 关于源码中的Lo ...

随机推荐

  1. AngularJS(2)-Scope作用域和控制器

    $scope: 根作用域 所有的应用都有一个 $rootScope,它可以作用在 ng-app 指令包含的所有 HTML 元素中. $rootScope 可作用于整个应用中.是各个 controlle ...

  2. linux下tomcat的安装

    本文主要内容: (1)安装apr,这是 Apache 为了提升 Tomcat 的性能搞的一套本地化 Socket, Thread, IO 组件也就是说它有高级 IO 功能, 操作系统级别的功能调用, ...

  3. PHP字符

    匹配查找 strstr strpos 通常用在表单验证里面可以用到 substr 正值表达式匹配 preg_mathc(), preg)mathc_all() , preg_grep() 编码格式的转 ...

  4. VB6-系统打印常识

    在一次做图片打印的时候,对位置的调整老是不得法,后来通过CBM666老师的帮助才解决问题,分享以下他给的帮助.     , , picA.Width , picA.Height Printer.End ...

  5. 《编写高质量代码:改善Python程序的91个建议》读后感

    编写高质量代码:改善Python程序的91个建议  http://book.douban.com/subject/25910544/ 1.(建议16)is 用于判断两个对象的id是否相等,==才是判断 ...

  6. BZOJ Tyvj 1729 文艺平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

  7. 剖析 Linux hypervisor--KVM 和 Lguest 简介

    慢慢弄清楚..   M. Tim Jones, 顾问工程师, Emulex Corp. M. Tim Jones 是一名嵌入式软件工程师,他是 Artificial Intelligence: A S ...

  8. JavaSE replaceAll 方法

    private String srcStr = "index\\.php\\?action=";//要替换的原字符串 private String destStr = " ...

  9. MySQL查询表结构的SQL小结

    mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; 示例: use testDB; # ...

  10. [状压dp]经典TSP

    0出发 每个顶点经过一次 回到0 最小花费. O($n^2 \times 2^n$) 记忆化搜索: // s: 已经访问过的节点状态 v: 出发位置 int dfs(int s, int v) { ) ...