一个简单到死的步科mt506t编程软件wen't

145449人阅读
网络/协议(15)
从一个简单的使用TCP例子开始socket编程,其基本步骤如下:
server&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& client
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++
创建socket&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 创建socket
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++
地址赋值(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 地址赋值(
自己的地址)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 服务器地址)
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
用bind绑定&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
socket和地址&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
listen&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
& & & | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++++
&&&&& | & &------------------------------& & & & & connect 服务器 &&&&&&&&
&&&&& | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ++++++++++
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
accept&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +++++++++
&&&&& | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& recv 和send
&&&&& | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 进行数据处理
&&&&& | &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +++++++++
+++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
用accept得到&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
的socket进行&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
recv 和 send&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
+++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +++++++++
close socket&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& close socket
+++++++++&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& +++++++++
根据以上步骤,服务器端的代码为
#include &stdio.h&
#include &string.h&
#include &sys/socket.h&
#include &netinet/in.h&
#include &stdlib.h&
#include &syslog.h&
#include &errno.h&
#define MAX_LISTEN_NUM 5
#define SEND_BUF_SIZE 100
#define RECV_BUF_SIZE 100
#define LISTEN_PORT 1010
int main()
int listen_sock = 0;
int app_sock = 0;
struct sockaddr_
struct sockaddr_
int socklen = sizeof(clientaddr);
char sendbuf[SEND_BUF_SIZE] = {0};
char recvbuf[RECV_BUF_SIZE] = {0};
int sendlen = 0;
int recvlen = 0;
int retlen = 0;
int leftlen = 0;
char *ptr = NULL;
memset((void *)&hostaddr, 0, sizeof(hostaddr));
memset((void *)&clientaddr, 0, sizeof(clientaddr));
hostaddr.sin_family = AF_INET;
hostaddr.sin_port = htons(LISTEN_PORT);
hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock & 0)
syslog(LOG_ERR, &%s:%d, create socket failed&, __FILE__, __LINE__);
if(bind(listen_sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr)) & 0)
syslog(LOG_ERR, &%s:%d, bind socket failed&, __FILE__, __LINE__);
if(listen(listen_sock, MAX_LISTEN_NUM) & 0)
syslog(LOG_ERR, &%s:%d, listen failed&, __FILE__, __LINE__);
app_sock = accept(listen_sock, (struct sockaddr *)&clientaddr, &socklen);
if(app_sock & 0)
syslog(LOG_ERR, &%s:%d, accept failed&, __FILE__, __LINE__);
sprintf(sendbuf, &welcome %s:%d here!/n&, inet_ntoa(clientaddr.sin_addr.s_addr), clientaddr.sin_port);
//send data
sendlen = strlen(sendbuf) +1;
retlen = 0;
//while(leftlen)
retlen = send(app_sock, ptr, sendlen, 0);
if(retlen & 0)
if(errno == EINTR)
retlen = 0;
leftlen -=
//receive data
recvlen = 0;
retlen = 0;
leftlen = RECV_BUF_SIZE -1;
retlen = recv(app_sock, ptr, leftlen, 0) ;
if(retlen & 0)
if(errno == EINTR)
retlen = 0;
recvlen +=
leftlen -=
//while(recvlen && leftlen);
printf(&receive data is : %s&, recvbuf);
close(app_sock);
close(listen_sock);
客户端代码为:
#include &stdio.h&
#include &string.h&
#include &sys/socket.h&
#include &netinet/in.h&
#include &syslog.h&
#include &errno.h&
#include &stdlib.h&
#define MAX_LISTEN_NUM 5
#define SEND_BUF_SIZE 100
#define RECV_BUF_SIZE 100
#define SERVER_PORT 1010
int main()
int sock_fd = 0;
char recvbuf[RECV_BUF_SIZE] = {0};
char sendbuf[SEND_BUF_SIZE] = {0};
int recvlen = 0;
int retlen = 0;
int sendlen = 0;
int leftlen = 0;
char *ptr = NULL;
struct sockaddr_in ser_
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
inet_aton(&127.0.0.1&, (struct in_addr *)&ser_addr.sin_addr);
ser_addr.sin_port = htons(SERVER_PORT);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd & 0)
syslog(LOG_ERR, &%s:%d, create socket failed&, __FILE__, __LINE__);
if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) & 0)
syslog(LOG_ERR, &%s:%d, connect socket failed&, __FILE__, __LINE__);
//receive data
recvlen = 0;
retlen = 0;
leftlen = RECV_BUF_SIZE -1;
retlen = recv(sock_fd, ptr, leftlen, 0) ;
if(retlen & 0)
if(errno == EINTR)
retlen = 0;
recvlen +=
leftlen -=
//while(recvlen && leftlen);
printf(&receive data is : %s&, recvbuf);
sprintf(sendbuf, &hello server/n&);
//send data
sendlen = strlen(sendbuf) +1;
retlen = 0;
// while(leftlen)
retlen = send(sock_fd, ptr, sendlen, 0);
if(retlen & 0)
if(errno == EINTR)
retlen = 0;
leftlen -=
close(sock_fd);
现在一个简单的使用tcp的socket通信的例子已经完成了,这里有几个需要说明的问题
1)头文件:
sys/socket.h&& 包含了socket相关的函数,如socket,send 和recv, 以及struct sockaddr等
netinet/in.h&&& 包含了地址结构,如struct sockaddr_in
errno.h&&&&&&&&&& 包含了errno 和 EINTR
syslog.h&&&&&&&& 包含了syslog相关的信息,其打印结果在/var/log/messages里面
2)socket地址
对于IPv4来说,其地址用的是struct sockaddr_in,具体结构如下
struct in_addr {
/* 32-bit IPv4 address */
/* network byte ordered */
struct sockaddr_in {
/* length of structure (16) */
sa_family_t
/* AF_INET */
/* 16-bit TCP or UDP port number */
/* network byte ordered */
struct in_addr
/* 32-bit IPv4 address */
/* network byte ordered */
sin_zero[8];
/* unused */
}; 其中sin_len我们一般不关注,也不填(只有在使用routing socket的时候才用到,被内核用来处理各种协议簇的地址结构)。bind, connect, sendto, 和 sendmsg会把socket地址从程序传递给内核; 而accept, recvfrom, recvmsg, getpeername, 和 getsockname会把地址从内核传递给程序。因为不同协议簇的地址结构是不一样的,所以必须要有一个通用的指针来传递地址,对于ANSI C来说我们一般使用void *,但是socket产生早于ANSI C,所以也就没有使用这个机制,而是使用一个通用的地址结构struct sockaddr来处理的struct sockaddr {
sa_family_t
/* address family: AF_xxx value */
sa_data[14];
/* protocol-specific address */
}; IPv6的socket地址为struct sockaddr_in6struct in6_addr {
s6_addr[16];
/* 128-bit IPv6 address */
/* network byte ordered */
#define SIN6_LEN
/* required for compile-time tests */
struct sockaddr_in6 {
/* length of this struct (28) */
sa_family_t
/* AF_INET6 */
/* transport layer port# */
/* network byte ordered */
sin6_ /* flow information, undefined */
struct in6_addr sin6_
/* IPv6 address */
/* network byte ordered */
sin6_scope_ /* set of interfaces for a scope */
对于sockaddr-in6来说,我们不能用通用的地址struct sockaddr来存储了,而是产用新的通用地址结构struct sockaddr_storage,这个结构足够大可以存储任何系统支持的地址。struct sockaddr_storage {
/* length of this struct (implementation dependent) */
sa_family_t
/* address family: AF_xxx value */
/* implementation-dependent elements to provide:
* a) alignment sufficient to fulfill the alignment requirements of
all socket address types that the system support
* b) enough storage to hold any type of socket address that the
system supports.
}; 几种常见的地址结构3) 相关函数的的length对于从程序传地址给内核的函数(如connect),其长度是一个整型值,告诉内核要copy的地址长度。对于从内核传递给程序的函数(如accpt),其长度是一个整型指针,是一个value-result参数。有两个目的:一告诉内核地址结构的长度,让内核在copy的时候不要超过这个长度;二返回内核真正copy的长度。4)字节序socket相关的函数都是使用网络字节序5)地址转换函数inet_aton, inet_ntoa, and inet_addr把IPv4字符串地址转为32位的网络字节序地址inet_ptonand inet_ntop可以转换IPv4和IPv6的地址6)listen中的backlog要知道这个值的含义先用说一下,对于一个listen的socket,有两个队列:一个是incomplete connection队列(仅仅收到SYN);一个是complete connection队列(三次握手完成)。accept函数就是在complete connection队列中取一个socket。backlog就是指队列的个数,但不行的是各个地方都没有明确定义这个值,没有说明究竟代表了哪个队列,或是两个队列之和。一般来说可以同时处理的连接数是backlog的1.5倍,很多地方都用5.7) getsockname 和 getpeername这两个函数可以与socket关联的地址,getsockname 和 getpeername分别得到自己和对端的地址
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen)
int getpeername(int sockfd , struct sockaddr * peeraddr , socklen_t * addrlen );
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1656603次
积分:12910
积分:12910
排名:第1018名
原创:171篇
转载:203篇
评论:89条
(1)(1)(2)(2)(3)(1)(2)(1)(1)(1)(1)(3)(1)(1)(2)(1)(3)(3)(4)(3)(3)(4)(4)(2)(2)(1)(2)(5)(5)(1)(2)(3)(6)(4)(6)(8)(12)(2)(9)(4)(32)(16)(19)(2)(1)(7)(13)(1)(5)(10)(8)(5)(3)(5)(3)(10)(23)(2)(7)(4)(6)(8)(3)(1)(1)(2)(4)(9)(6)(2)(2)(8)(4)(6)(2)(1)(4)(4)(2)(1)

我要回帖

更多关于 mt4414t编程软件 的文章

 

随机推荐