1 常用函数

1.1   connect()

int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen);

  客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1,程序会阻塞。

1.2   bind():很少用

  由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。注意,客户端不是不允许调用bind(),只是没有必要调用bind()固定一个端口号,服务器也不是必须调用bind(),但如果服务器不调用bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。

2 客户端的简单实现(C语言)

功能:连接到服务器后,如果服务器发送数据,则返回服务器发送的数据

unsigned char TcpRecvBuf[1520]  /* 缓存区,完整的以太帧最大也就1520或1518字节,如果去掉协议部分则可以更小 */
static void Task_TCP_Client (void *pdata)
{
struct sockaddr_in server, client;
int sock, iState;
int statusOk = 0; struct ip_addr stIpAddr;
IP4_ADDR(&stIpAddr, REMOTE_IP_0, REMOTE_IP_1, REMOTE_IP_2, REMOTE_IP_3);
server.sin_family = AF_INET; /* 服务器地址类型为IPV4 */
server.sin_port = htons(80); /* 服务器的端口号为5000 */
server.sin_addr.s_addr = stIpAddr.addr; /* 服务器的IP地址 */
   /*
* 以下4行为设置客户端的属性,可以不要,有系统自动分配端口号。即不调用bind函数。
*/
client.sin_family = AF_INET;
client.sin_port = htons( 4000 ); /* 设置客户端的端口 */
client.sin_addr.s_addr = htonl( INADDR_ANY );
bind( sock, (struct sockaddr *)&client, sizeof( client ) );/* 绑定本地接口 */
sock = socket( AF_INET, SOCK_STREAM, 0 ); /* 使用TCP连接 */
/*
* 试图与服务器建立连接,阻塞程序
*/
iState = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
while(1) {
statusOk = read(sock, TcpRecvBuf, sizeof(TcpRecvBuf));
if (statusOk > 0) {
statusOk = write(sock, TcpRecvBuf,statusOk);
}
if (statusOk <= 0){
iState = -1;
while (iState == -1) {
close( sock ); /* 关闭此连接 */
/*
* 下面将重新与服务器建立连接
*/
sock = socket( AF_INET, SOCK_STREAM, 0 ); /* 使用TCP连接 */
bind( sock, (struct sockaddr *)&client, sizeof( client ) );/* 绑定本地接口 */
iState = connect(sock, (struct sockaddr *)&server, sizeof( server ));
OSTimeDly(100); // 延迟一会儿,(ucos-ii的延迟函数,可以用其它延迟函数替代)
}
}
}
}

socket编程中服务器端常用函数 以及简单实现

 

1 常用函数

1.1   socket()

int socket(int family, int type, int protocol);

  socket()打开一个网络通讯端口,如果成功的话,返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。对于IPv4,family参数指定为AF_INET。对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。protocol参数的介绍从略,指定为0即可。

1.2   bind()

int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

  服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。bind()成功返回0,失败返回-1。bind()的作用是将参数sockfd和myaddr绑定在一起,使sockfd这个用于网络通讯的文件描述符监听myaddr所描述的地址和端口号。前面讲过,struct sockaddr *是一个通用指针类型,myaddr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度

1.3   listen()

int listen(int sockfd, int backlog);// backlog取值0~5.

  典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。listen()成功返回0,失败返回-1。

1.4   accept()

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

  三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。cliaddr是一个传出参数,accept()返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-result argument),传入的是调用者提供的缓冲区cliaddr的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给cliaddr参数传NULL,表示不关心客户端的地址。

2 简单实现服务器编程(C语言)

 1 unsigned char TcpRecvBuf[1520];                              /* 接收缓冲区 */
2 static void Task_WebServer (void *pdata)
3 {
4 struct sockaddr_in server, client;
5 int sock, client_socket;
6 socklen_t len;
7
8 server.sin_family = AF_INET; /* 地址类型为IPv4 */
9 server.sin_port = htons( 80 ); /* 设置服务器的端口:80端口 */
10 server.sin_addr.s_addr = htonl( INADDR_ANY ); /* 监听本地任意网卡 */
11 sock = socket( AF_INET, SOCK_STREAM, 0 ); /* 使用TCP连接 */
12 bind( sock, (struct sockaddr *)&server, sizeof( server ) );/* 绑定本地接口 */
13 listen( sock, 5 ); /* 进入监听模式 */
14 while(1) {
15 len = sizeof(client);
16 client_socket = accept( sock, (struct sockaddr *)&client, &len );/* 接受一个连接,会阻塞程序 */
17 if(client_socket != -1) {
18 /*
19 * 接收数据,将会阻塞程序
20 */
21 if ((read(client_socket, TcpRecvBuf, sizeof(TcpRecvBuf))) > 0) {
22 /*
23 * 简单的检查数据是否符合HTTP协议,数据内容开头是“GET /”
24 */
25 if(TcpRecvBuf[0] == 'G' && TcpRecvBuf[1] == 'E' &&
26 TcpRecvBuf[2] == 'T' && TcpRecvBuf[3] == ' ' &&
27 TcpRecvBuf[4] == '/') {
28 /**
29 * 下面为GET请求返回的数据,用户可以自己定义
30 */
31 //write(client_socket, http_html_hdr,sizeof(http_html_hdr));
32 //write(client_socket, indexdata,sizeof(indexdata));
33 }
34 }
35 close( client_socket ); /* 关闭此连接 */
36 }
37 /** 这里可以延时一定时间 */
38 }
39 }

函数原型:

int listen(int  sockfd, int  backlog);

当服务器编程时,经常需要限制客户端的连接个数,下面为问题分析以及解决办法:

下面只讨论TCP  UDP不做讨论(很少使用到listen函数)
  listen函数用法:函数应该在调用socket和bind这两个函数之后,accept函数之前调用。
  listen函数作用:让服务器套接字sockfd进入监听状态。

1.返回值:

  成功返回0;

  失败返回-1。

2.参数:
    sockfd:套接字,成功返回后进入监听模式,当有新连接并accept后会再建立一个套接字保存新的连接;
    backlog:暂且翻译为后备连接吧!下面详细介绍此参数:

  1)  当TCP接收一个连接后(三次握手通过)会将此连接存在连接请求队列里面,并对队列个数+1,而backlog为此队列允许的最大个数,超过此值,则直接将新的连接删除,即不在接收新的连接。将这些处于请求队列里面的连接暂记为后备连接,这些都在底层自动完成,底层将连接添加到队列后等待上层来处理(一般是调用accept函数接收连接);

  2)  当上层调用accept函数接收一个连接(处于请求队列里面的后备连接),队列个数会-1;

  3)  那么这样一个加一个减,只要底层提交的速度小于上层接收的速度(一般是这样),很明显backlog就不能限制连接的个数,只能限制后备连接的个数。那为啥要用这个backlog呢?主要用于并发处理,当上层没来的及接收时,底层可以提交多个连接;

  4)  backlog的取值范围 ,一般为0-5。

socket编程中客户端常用函数的更多相关文章

  1. socket编程中客户端常用函数 以及简单实现

    1 常用函数 1.1   connect() int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen); 客 ...

  2. socket编程中服务器端常用函数 以及简单实现

    1 常用函数 1.1   socket() int socket(int family, int type, int protocol); socket()打开一个网络通讯端口,如果成功的话,返回一个 ...

  3. socket编程中write、read和send、recv之间的区别~转载

    socket编程中write.read和send.recv之间的区别   http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立 ...

  4. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

  5. perl编程中的map函数示例

    转自:http://www.jbxue.com/article/14854.html 发布:脚本学堂/Perl  编辑:JB01   2013-12-20 10:20:01  [大 中 小] 本文介绍 ...

  6. Mysql中的常用函数:

    Mysql中的常用函数: 1.字符串函数: (1).合并字符串 concat():// concat('M','y',"SQL",'5.5');== MySQL5.5//当传入的参 ...

  7. PHP socket 编程中的超时设置

    PHP socket 编程中的超时设置.网上找了半天也没找到.贴出来分享之:设置$socket 发送超时1秒,接收超时3秒: $socket = socket_create(AF_INET,SOCK_ ...

  8. numpy函数库中一些常用函数的记录

    ##numpy函数库中一些常用函数的记录 最近才开始接触Python,python中为我们提供了大量的库,不太熟悉,因此在<机器学习实战>的学习中,对遇到的一些函数的用法进行记录. (1) ...

  9. 【C/C++开发】多线程编程中的join函数

    多线程编程中的join函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # coding: utf-8 # 测试多线程中join的 ...

随机推荐

  1. 【嵌入式开发】C语言 指针数组 多维数组

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...

  2. android开发之http协议

    http协议学习系列 1. 基础概念篇 1.1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(World Wide Web C ...

  3. iOS监听模式系列之iOS开发证书、秘钥

    补充--iOS开发证书.秘钥 iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书,对于初学者往往迷惑不解,再加上今天的文章中会牵扯到一些特殊配置,这里就简单的对iOS开发的常用证书和秘钥等 ...

  4. 文件lseek操作产生空洞文件的方法

    在文件操作过程中,lseek操作可以偏移到文件的任意位置. 在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的 ...

  5. android JNI调用机制

    JNI的出现使得开发者既可以利用Java语言跨平台.类库丰 富.开发便捷等特点,又可以利用Native语言的高效. JNI是JVM实现中的一部分,因此Native语言和Java代码都运行在JVM的宿主 ...

  6. obj-c中SEL签名和Invocation示例

    参考小示例,代码如下: #import <Foundation/Foundation.h> @interface PlayList:NSObject @property NSMutable ...

  7. how tomcat works 总结

    希望各位网友在看完<<how tomcat works>>一书或者鄙人的tomcat专栏文章后再看这篇博客 这里主要是梳理各个章节的核心概念 第一章 一个简单的Web服务器 第 ...

  8. obj-c编程01[扩展学习01]:对象消息机制工作原理

    obj-c中的类就像C语言中的struct.NSObject类声明一个成员变量isa,因为NSObject类是整个继承树的根,所以每个类中都有一个isa其指向创建的对象.在类结构中有实例变量(成员变量 ...

  9. mysql 2003错误

    mysql安装好经常发现无法正常启动碰到最多的是error 2003的错误,以下为解决方法: mysqld -nt -remove mysqld -nt -install 重新启动mysql net ...

  10. 重写,string创建内存问题

     //重写equals方法,因为我们要对比的是date类中的时间而不是对象的引用地址 51     //如果传递的是Object类的话,我们就需要重写hashCode()方法,这样就比较麻烦,而且暂时 ...