I/O示例使用一个windows平台上服务器/客户端的例子来演示。由于为了减少代码篇幅等各种由于本人懒而产生的原因,以下代码没有做错误处理以及有些小问题,但是我想应该不影响演示,大家多包涵。
服务器代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include <stdio.h> #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include "event.h" #include "event_struct.h" #include "evutil.h" #define PORT 4000 #define IP_ADDRESS "172.16.80.101" #define MEM_SIZE 1024 struct event_base* base; struct sock_ev { struct event* read_ev; struct event* write_ev; char * buffer; }; void release_sock_event( struct sock_ev* ev) { event_del(ev->read_ev); free (ev->read_ev); free (ev->write_ev); free (ev->buffer); free (ev); return ; } void on_write( int sock, short event, void * arg) { char * buffer = ( char *)arg; send(sock, buffer, strlen (buffer), 0); printf ( "on_write
" ); free (buffer); return ; } void on_read( int sock, short event, void * arg) { struct event* write_ev; int size; struct sock_ev* ev = ( struct sock_ev*)arg; printf ( "on_read
" ); ev->buffer = ( char *) malloc (MEM_SIZE); memset (ev->buffer, 0, MEM_SIZE); size = recv(sock, ev->buffer, MEM_SIZE, 0); printf ( "receive data:%s, size:%d
" , ev->buffer, size); if (size == 0) { release_sock_event(ev); close(sock); return ; } event_assign(ev->write_ev, base, sock, EV_WRITE, on_write, ev->buffer); event_add(ev->write_ev, NULL); return ; } void on_accept( int sock, short event, void * arg) { struct sockaddr_in cli_addr; int fd, sin_size; struct sock_ev* ev = ( struct sock_ev*) malloc ( sizeof ( struct sock_ev)); printf ( "on_accept
" ); ev->read_ev = ( struct event*) malloc ( sizeof ( struct event)); ev->write_ev = ( struct event*) malloc ( sizeof ( struct event)); sin_size = sizeof ( struct sockaddr_in); fd = accept(sock, ( struct sockaddr*)&cli_addr, &sin_size); event_assign(ev->read_ev, base, fd, EV_READ|EV_PERSIST, on_read, ev); event_add(ev->read_ev, NULL); return ; } int main( int argc, char * argv[]) { WSADATA ws; SOCKET srvSock; struct sockaddr_in sockAddr; struct event ev_listen; WSAStartup(MAKEWORD(2,2), &ws); srvSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS); sockAddr.sin_port = htons(PORT); memset (sockAddr.sin_zero, 0, sizeof (sockAddr.sin_zero)); bind(srvSock, ( struct sockaddr*)&sockAddr, sizeof (sockAddr)); listen(srvSock, 10); base = event_base_new(); event_assign(&ev_listen, base, srvSock, EV_READ|EV_PERSIST, on_accept, NULL); event_add(&ev_listen, NULL); event_base_dispatch(base); closesocket(srvSock); WSACleanup(); return 0; } |
|
|
客户端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#include "stdafx.h" #include <stdio.h> #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include "event.h" #include "event_struct.h" #include "evutil.h" #define PORT 4000 #define IP_ADDRESS "172.16.80.101" int main( int argc, char * argv[]) { WSADATA ws; SOCKET cltSocket; struct sockaddr_in sockAddr; int Ret = 0; WSAStartup(MAKEWORD(2,2), &ws); cltSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS); sockAddr.sin_port = htons(PORT); memset (sockAddr.sin_zero, 0, sizeof (sockAddr.sin_zero)); connect(cltSocket,( struct sockaddr*)&sockAddr, sizeof (sockAddr)); //send char SendBuffer[MAX_PATH] = "test" ; Ret = send(cltSocket, SendBuffer, ( int ) strlen (SendBuffer), 0); printf ( "send size=%d.
" , Ret); //recv char recvBuf[50] = {0}; if ( 0 > recv(cltSocket, recvBuf, 50, 0) ) { printf ( "recv fail.
" ); return 0; } printf ( "%s
" , recvBuf); while (1) { Sleep(1000); } closesocket(cltSocket); WSACleanup(); return 0; } |
服务器的功能主要是接收客户端发来的数据,并返回给客户端。
客户端的功能主要是连接服务器后向服务器发送数据,然后读取服务器发来的数据。
下面分下以下代码流程:
客户端就不分析了,都是老套路。
服务器端:
(1) 首先添加一个永久的读类型的事件,指定的文件描述符是我们监听的socket。当有客户端来connect,这个事件会触发,触发回调函数on_accept()。
(2) 在on_accept()中accept后,在新的文件描述符上添加一个永久的读事件,当文件操作符可读,调用on_read()读取。
(3) 在on_read()中为了将数据写会给客户端,添加了一个写事件,这次的写事件不是永久的,只会触发一次,因为我们只将读取到的数据回给客户端一次。当文件描述符可写,触发回调函数on_write()写入给客户端。
(4) On_write()写入数据。