基础知识
(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
原文地址:http://10707460.blog.51cto.com/10697460/1775745