码迷,mamicode.com
首页 > 其他好文 > 详细

套接字编程——基于TCP协议

时间:2016-05-22 00:51:23      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:网络通讯   网络连接   tcp协议   ip地址   服务器   

  1. 基础知识

    (1)socket

    a. 什么是socket?

      socket这个词可以表示很多概念,这儿我们讲的socket是:“IP地址+端口号(TCP或UDP端口号)”。在TCP/IP协议中,它唯一标识网络通讯中的一个进程。


    b. socket有什么用?

      在TCP协议中,建立连接的两个进程各自有一个socket来标识,这两个socket组成 的socket pair就唯一标识一个连接。socket本身有“插座”的意思,因此用来描述网络连接的一 对一关系。


    c.什么叫socketAPI

      为TCP/IP协议设计的应用层编程接口称为socketAPI。


2. 程序实现图

服务器:调用socket()、bind()、listen() 完成初始化后,调用accept()阻塞等待,处于监听端口的状

态,

客户端:调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后 从accept()返回。

技术分享


3. 相关函数

(1)创建套接字——socket()

技术分享

a.  参数

domain:表示底层通信所使用的协议,有很多选项。这儿我们选择AF_INET格式,IPv4网络协议;

type:表示协议实现的方式,也有很多选项。这儿我们用SOCK_STREAM,它 提供有序的、可靠的、双向的和基于连接的字节流,使用带外数据传送机制,为Internet地址族使用TCP。 (在UDP中,我们使用参数SOCK_DGRAM ,它支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务);

protocol:套接口所用的协议。前面两个参数设定后,这儿可用0指定,表示缺省。

b. 返回值

成功返回新创建socket的文件描述符,失败返回-1


(2)绑定端口——bind()

技术分享

a.   参数

sockfd:表示一个已经建立的socket编号(描述符);

addr:指向sockaddr结构体类型的指针;

addrlen:addr结构的长度,可以用sizeof函数获得。


b. 返回值

成功返回0,失败返回-1。


(3)监听客户请求——listen()

技术分享

a. 参数

sockfd:表示一个已经建立的socket编号(描述符);

backlog:连接请求队列的最大长度; 


b. 返回值

成功返回0,失败返回-1。


(4)接受客户端连接——accept()

技术分享

返回值: 成功返回接受的socket文件描述符,失败返回-1。


(5)连接服务器——connect()

技术分享

返回值:成功返回0,失败返回-1。


4. 数据传输的过程

建立连接后,TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主 动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()返回后立刻调 用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送 请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞 等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。

如果客户端没有更多的请求了,就调用close() 关闭连接,就像写端关闭的管道一样,服务器 的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注意,任何一方调用close() 后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown() 则连接处 于半关闭状态,仍可接收对方发来的数据。


5. 代码实现

//tcp_server.cpp
 1 #include<iostream>
  2 #include<string>
  3 #include<string.h>
  4 #include<stdlib.h>
  5 #include<sys/socket.h>
  6 #include<sys/types.h>
  7 #include<netinet/in.h>
  8 #include<arpa/inet.h>
  9 #include<errno.h>
 10 #include<pthread.h>
 11 
 12 using namespace std;
 13 const int g_backlog=5;
 14 
 15 void usage(string _proc)
 16 {   
 17     cout<<"Usage:"<<_proc<<"[ip][port]"<<endl;
 18 }
 19 static int startup(const string &ip,const int &port)
 20 {
 21     //1.
 22     int sock=socket(AF_INET,SOCK_STREAM,0);
 23     if(sock<0)
 24     {
 25         cerr<<strerror(errno)<<endl;
 26         exit(1);
 27     }
 28     //2.
 29     struct sockaddr_in local;
 30     local.sin_family=AF_INET;
 31     local.sin_port=htons(port);
 32     local.sin_addr.s_addr=inet_addr(ip.c_str());
 33     //3.
 34     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 35     {
 36         cerr<<strerror(errno)<<endl;
 37         exit(2);
 38     }
 39     //4.
 40     if(listen(sock,g_backlog)<0)
 41     {
 42         cerr<<strerror(errno)<<endl;
 43         exit(3);
 44     }
 45     return sock;
 46 }
 47 void *thread_run(void *arg)
 48 {
 49     int sock=(int)arg;
 50     char buf[1024];
 51     while(1)
 52     {
 53         memset(buf,‘\0‘,sizeof(buf));
 54         ssize_t _size=read(sock,buf,sizeof(buf)-1);
 55         if(_size>0)
 56         {
 57             //read success
 58             buf[_size]=‘\0‘;
 59         }
 60         else if(_size==0)
 61         {
 62             //client close
 63             cout<<"client close..."<<endl;
 64             break;
 65         }
 66         else
 67         {
 68             cout<<strerror(errno)<<endl;
 69         }
 70         cout<<"client# "<<buf<<endl;
 71         }
 72     //close(sock);
 73     return NULL;
 74 }
 75 
 76 int main(int argc,char* argv[])
 77 {
 78     if(argc!=3)
 79     {
 80         usage(argv[0]);
 81         exit(1);
 82     }
 83     string ip=argv[1];
 84     int port=atoi(argv[2]);
 85     int listen_sock=startup(ip,port);
 86 
 87     struct sockaddr_in client;
 88     socklen_t len = sizeof(client);
 89     while(1)
 90     {
 91         int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
 92         if(new_sock<0)
 93         {
 94             cerr<<strerror(errno)<<endl;
 95             continue;
 96         }
 97         cout<<"get a connect..."<<"sock:"<<new_sock 98             <<"ip:"<<inet_ntoa(client.sin_addr)<<"port:" 99             <<ntohs(client.sin_port)<<endl;
100 #ifdef _v1_
101         //version 1
102         char buf[1024];
103         while(1)
104         {
105             ssize_t _size=read(new_sock,buf,sizeof(buf)-1);
106             if(_size>0)
107             {
108                 //read success
109                 buf[_size]=‘\0‘;
110             }
111             else if(_size==0)
112             {
113                 //client close
114             }
115             else
116             {
117                 cout<<strerror(errno)<<endl;
118             }
119             cout<<"client# "<<buf<<endl;
120         }
121 #elif _v2_
122         cout<<"v2"<<endl;
123         pid_t id =fork();
124         if(id==0)
125         {
126             //child
127             std::string _client=inet_ntoa(client.sin_addr);
128             close(listen_sock);
129             char buf[1024];
130             while(1)
131             {
132                 memset(buf,‘\0‘,sizeof(buf));
133                 ssize_t _size=read(new_sock,buf,sizeof(buf)-1);
134                 if(_size>0)
135                 {
136                     //read success
137                     buf[size]=‘\0‘;
138                 }
139                 else if(_size==0)
140                 {
141                     //client close
142                     cout<<_client<<"close..."<<endl;
143                     break;
144                 }
145                 else
146                 {
147                     cout<<strerror(errno)<<endl;
148                 }
149                 cout<<_client<<"# "<<buf<<endl;
150             }
151             close(new_sock);
152             exit(0);
153         }
154         else if(id>0)
155         {
156             close(new_sock);
157         }
158         else
159         {}
160 #elif _v3_
161         pthread_t tid;              
162         pthread_create(&tid,NULL,thread_run,(void*)new_sock);
163         pthread_detach(tid);
164 #else
165     cout<<"default"<<endl;
166 #endif
167 }
168 return 0;
169 }  

//tcp_client.cpp
  1 #include<iostream>
  2 #include<string>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<stdlib.h>
  6 #include<sys/socket.h>
  7 #include<sys/types.h>
  8 #include<netinet/in.h>
  9 #include<arpa/inet.h>
 10 #include<errno.h>
 11 
 12 using namespace std;
 13 void usage(string _proc)
 14 {
 15     cout<<_proc<<"[remote ip] [remote port]"<<endl;
 16 }
 17 int main(int argc,char* argv[])
 18 {
 19     if(argc!=3)
 20     {
 21         usage(argv[0]);
 22         exit(1);
 23     }
 24 
 25     int r_port=atoi(argv[2]);
 26     string r_ip=argv[1];
 27 
 28     int sock=socket(AF_INET,SOCK_STREAM,0);
 29     if(sock<-1)
 30     {
 31         cout<<strerror(errno)<<endl;
 32         exit(1);
 33     }
 34 
 35     struct sockaddr_in remote;
 36     remote.sin_family=AF_INET;
 37     remote.sin_port=htons(r_port);
 38     remote.sin_addr.s_addr=inet_addr(r_ip.c_str());
 39 
 40     int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
 41     if(ret<0)
 42     {
 43         cout <<strerror(errno)<<endl;
 44     }
 45     string msg;
 46     while(1)
 47     {
 48         cout<<"please Enter:";
 49         cin>>msg;
 50         write(sock,msg.c_str(),msg.size());
 51     }
 52     return 0;
 53 }
 
 //makefile
  1 .PHONY:all
  2 all:tcp_client tcp_server
  3 tcp_client:tcp_client.cpp
  4     g++ -o $@ $^
  5 tcp_server:tcp_server.cpp
  6     g++ -o $@ $^ -lpthread -D_v3_
  7 .PHONY:clean
  8 clean:
  9     rm -f tcp_client tcp_server
  
  //statr.sh
  1 #!/bin/bash
  2 
  3 service iptables stop
  4 ./tcp_server 192.168.163.128 8080


本文出自 “sunshine225” 博客,请务必保留此出处http://10707460.blog.51cto.com/10697460/1775745

套接字编程——基于TCP协议

标签:网络通讯   网络连接   tcp协议   ip地址   服务器   

原文地址:http://10707460.blog.51cto.com/10697460/1775745

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!