1
/*
socket->bind->listen->accept->recv/recvfrom->send/sendto->close
2
3
客戶端:socket->connect->send/sendto->recv/recvfrom->close
4
5
其中服務(wù)器端首先建立起socket,然后調(diào)用本地端口的綁定,接著就開(kāi)始與客服端建立聯(lián)系,并接收客戶端發(fā)送的消息。
6
客戶端則在建立socket之后調(diào)用connect函數(shù)來(lái)建立連接。
7
8
服務(wù)器端的源代碼如下所示:
*/
9
10
/*
"server.c"
*/
11
12
#include<sys/types.h>
13
#include<sys/socket.h>
14
#include<stdio.h>
15
#include<stdlib.h>
16
#include<errno.h>
17
#include<
string
.h>
18
#include<unistd.h>
19
#include<netinet/
in
.h>
20
21
#define
PORT 3490
//
端口
22
23
#define
BUFFER_SIZE 1024
//
緩沖區(qū)大小
24
25
#define
MAX_QUE_CONN_NM 5
//
服務(wù)器等待連接隊(duì)列的最大長(zhǎng)度。
26
27
int
main(){
28
29
struct
sockaddr_in server_sockaddr,client_sockaddr;
//
分別定義服務(wù)器和客戶端套接字
30
int
sin_size,recvbytes;
31
int
server_fd,client_fd;
32
char
buf[BUFFER_SIZE];
//
緩沖區(qū)
33
34
/*
35
SOCKET PASCAL FAR socket( int af, int type, int protocol);
36
af:一個(gè)地址描述。目前僅支持AF_INET格式,也就是說(shuō)ARPA Internet地址格式。
37
type:指定socket類型。新套接口的類型描述類型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。
38
常用的socket類型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
39
protocol:顧名思義,就是指定協(xié)議。套接口所用的協(xié)議。如調(diào)用者不想指定,可用0。
40
常用的協(xié)議有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,
41
它們分別對(duì)應(yīng)TCP傳輸協(xié)議、UDP傳輸協(xié)議、STCP傳輸協(xié)議、TIPC傳輸協(xié)議。
42
*/
43
if
((server_fd = socket(AF_INET,SOCK_STREAM,
0
))== -
1
){
//
建立socket連接www.linuxidc.com
44
perror(
"
create socket fail
"
);
45
exit(
1
);
46
}
47
48
printf(
"
Socket id=%d\n
"
,server_fd);
49
50
/*
設(shè)置sockaddr_in結(jié)構(gòu)體中的相關(guān)參數(shù)
*/
51
52
server_sockaddr.sin_family =
AF_INET;
53
server_sockaddr.sin_port = htons(PORT);
//
由于在寫網(wǎng)絡(luò)程序時(shí)字節(jié)的網(wǎng)絡(luò)順序和主機(jī)順序會(huì)有問(wèn)題
54
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
//
即0.0.0.0 任意地址
55
bzero(&(server_sockaddr.sin_zero),
8
);
56
int
i =
1
;
//
允許重復(fù)使用本地地址與套接字進(jìn)行綁定
57
58
/*
int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char FAR *optval,int optlen);
59
s:標(biāo)識(shí)一個(gè)套接字的描述符。
60
level:選項(xiàng)定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。
61
optname:需設(shè)置的選項(xiàng)。
62
optval:指針,指向存放選項(xiàng)值的緩沖區(qū)。
63
optlen:optval緩沖區(qū)長(zhǎng)度。
64
*/
65
setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&i,
sizeof
(i));
66
67
/*
68
int bind(SOCKET socket, const struct sockaddr *address,
69
socklen_t address_len);
70
參數(shù)說(shuō)明:
71
socket:是一個(gè)套接字。
72
address:是一個(gè)sockaddr結(jié)構(gòu)指針,該結(jié)構(gòu)中包含了要結(jié)合的地址和端口號(hào)。
73
address_len:確定address緩沖區(qū)的長(zhǎng)度。
74
返回值:如果函數(shù)執(zhí)行成功,返回值為0,否則為SOCKET_ERROR。
75
*/
76
if
(bind(server_fd,(
struct
sockaddr *)&server_sockaddr,
sizeof
(
struct
sockaddr)) == -
1
){
//
綁定函數(shù)bind
77
perror(
"
bind fail
"
);
78
exit(
1
);
79
}
80
81
printf(
"
Bind success!\n
"
);
82
83
/*
84
int PASCAL FAR listen( SOCKET s, int backlog);
85
S:用于標(biāo)識(shí)一個(gè)已捆綁未連接套接口的描述字。
86
backlog:等待連接隊(duì)列的最大長(zhǎng)度。
87
*/
88
if
(listen(server_fd,MAX_QUE_CONN_NM)== -
1
){
//
調(diào)用listen函數(shù),創(chuàng)建為處理請(qǐng)求的隊(duì)列
89
perror(
"
listen fail
"
);
90
exit(
1
);
91
}
92
93
printf(
"
Listening......\n
"
);
94
95
/*
96
SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen);
97
s:套接口描述字,該套接口在listen()后監(jiān)聽(tīng)連接。
98
addr:(可選)指針,指向一緩沖區(qū),其中接收為通訊層所知的連接實(shí)體的地址。Addr參數(shù)的實(shí)際格式由套接口創(chuàng)建時(shí)所產(chǎn)生的地址族確定。
99
addrlen:(可選)指針,輸入?yún)?shù),配合addr一起使用,指向存有addr地址長(zhǎng)度的整型數(shù)。
100
*/
101
if
((client_fd = accept(server_fd,(
struct
sockaddr *)&client_sockaddr,&sin_size))==-
1
){
//
調(diào)用accept函數(shù),等待客戶端的接
102
perror(
"
accept fail
"
);
103
exit(
1
);
104
}
105
106
printf(
"
server: got connection from %s \n
"
,inet_ntoa(client_sockaddr.sin_addr));
107
108
memset(buf,
0
,
sizeof
(buf));
109
/*
110
int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);
111
s:一個(gè)標(biāo)識(shí)已連接套接口的描述字。
112
buf:用于接收數(shù)據(jù)的緩沖區(qū)。
113
len:緩沖區(qū)長(zhǎng)度。
114
flags:指定調(diào)用方式。通常寫成0
115
*/
116
if
((recvbytes = recv(client_fd,buf,BUFFER_SIZE,
0
)) == -
1
){
//
調(diào)用recv函數(shù)接收客戶端的請(qǐng)求
117
perror(
"
recv fail
"
);
118
exit(
1
);
119
}
120
121
printf(
"
Received a message: %s\n
"
,buf);
122
123
124
/*
向客戶起寫數(shù)據(jù)
*/
125
if
(write(client_fd,
"
客戶端我收到你發(fā)來(lái)的數(shù)據(jù)了,你能收到這句應(yīng)答嗎?\n
"
,
1024
)==-
1
)
126
perror(
"
write error!
"
);
127
128
close(client_fd);
129
130
close(server_fd);
131
exit(
0
);
132
}
133
134
135
136
137
138
/*
客戶端
*/
139
/*
client.c 運(yùn)行方式:./client localhost
*/
140
#include <stdio.h>
141
#include <stdlib.h>
142
#include <errno.h>
143
#include <
string
.h>
144
#include <netdb.h>
145
#include <sys/types.h>
146
#include <netinet/
in
.h>
147
#include <sys/socket.h>
148
#define
PORT 3490
149
#define
MAXDATASIZE 5000
150
int
main(
int
argc,
char
**
argv)
151
{
152
int
sockfd,nbytes;
153
char
buf[
1024
];
154
struct
hostent *
he;
155
struct
sockaddr_in srvaddr;
156
if
(argc!=
2
)
157
{
158
perror(
"
Usage:client hostname\n
"
);
159
exit(
1
);
160
}
161
/*
函數(shù)gethostbyname獲得指定域名地址所對(duì)應(yīng)的ip地址
*/
162
if
((he=gethostbyname(argv[
1
]))==
NULL)
163
{
164
perror(
"
gethostbyname
"
);
165
exit(
1
);
166
}
167
/*
創(chuàng)建套接字,返回套接字描述符
*/
168
if
((sockfd=socket(AF_INET,SOCK_STREAM,
0
))==-
1
)
169
{
170
perror(
"
create socket error
"
);
171
exit(
1
);
172
}
173
bzero(&srvaddr,
sizeof
(srvaddr));
174
/*
用獲得的遠(yuǎn)程服務(wù)器進(jìn)程的ip地址和端口號(hào)來(lái)填充一個(gè)internet套接字地址結(jié)構(gòu)
*/
175
srvaddr.sin_family=
AF_INET;
176
srvaddr.sin_port=
htons(PORT);
177
srvaddr.sin_addr=*((
struct
in_addr *)he->
h_addr);
178
/*
用connect于這個(gè)遠(yuǎn)程服務(wù)器建立一個(gè)internet連接
*/
179
if
(connect(sockfd,(
struct
sockaddr *)&srvaddr,
sizeof
(
struct
sockaddr))==-
1
)
180
{
181
perror(
"
connect error
"
);
182
exit(
1
);
183
}
184
185
186
if
((send(sockfd,
"
客戶端向服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端你收到了嗎?
"
,
1024
,
0
)) == -
1
)
187
{
188
perror(
"
send error
"
);
189
exit(
1
);
190
}
191
192
193
194
/*
調(diào)用read函數(shù)讀取服務(wù)器write過(guò)來(lái)的信息
*/
195
if
((nbytes=read(sockfd,buf,MAXDATASIZE))==-
1
)
196
{
197
perror(
"
read error
"
);
198
exit(
1
);
199
}
200
buf[nbytes]=
'
\0
'
;
201
printf(
"
read: %s
"
,buf);
202
close(sockfd);
203
}
?
運(yùn)行方式: gcc -o service service.c
gcc -o client client.c
chmod +x service
chmod +x client
在一個(gè)終端運(yùn)行:./service
在另一個(gè)終端運(yùn)行:./client localhost
服務(wù)端輸出:
Socket id=3 Bind success! Listening...... server: got connection from 127.0.0.1 Received a message: 客戶端向服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端你收到了嗎?
?
客戶端輸出:
read: 客戶端我收到你發(fā)來(lái)的數(shù)據(jù)了,你能收到這句應(yīng)答嗎?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

