爲了簡單,這個程序沒有套接字的錯誤處理邏輯。原文件名跟傳輸後存儲的文件名都是程序裏寫死的。
如果想得到更安全的網絡編程例子,推薦 《網絡編程 卷1》,這本書真的講得很好,很詳細。
簡單的網絡編程無非就是那幾步。
創建服務端
1.創建套接字
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
2.綁定地址
struct sockaddr_in channel;
memset(&channel, 0, sizeof(channel));
channel.sin_family = AF_INET;
channel.sin_port = htons(SERVER_PORT);
channel.sin_addr.s_addr = htonl(INADDR_ANY);
INADDR_ANY 表示任何地址都可以連接這個套接字 ,網絡字節序是big endian。
3.監聽
listen(s,5);
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
DESCRIPTION
listen() marks the socket referred to by sockfd as a passive socket,
that is, as a socket that will be used to accept incoming connection
requests using accept(2).
The sockfd argument is a file descriptor that refers to a socket of
type SOCK_STREAM or SOCK_SEQPACKET.
The backlog argument defines the maximum length to which the queue of
pending connections for sockfd may grow. If a connection request
arrives when the queue is full, the client may receive an error with an
indication of ECONNREFUSED or, if the underlying protocol supports
retransmission, the request may be ignored so that a later reattempt at
connection succeeds.
4.接受連接
int acc = accept(s, 0,0);
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
addr,與addrlen 是返回客戶端連接的套接字綁定的地址,如果我們不需要連接的客戶端地址的話,可以將此兩值賦爲NULL。
5.傳輸數據
read(), write().
創建客戶端
1.創建套接字
同創建服務端
2.創建連接
struct sockaddr_in channel;
memset(&channel, 0, sizeof(channel));
channel.sin_family = AF_INET;
channel.sin_port = htons(SERVER_PORT);
channel.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s, (struct sockaddr* )&channel, sizeof(channel));
SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
The inet_addr() function converts the Internet host address cp from IPv4 numbers-and-dots notation into binary data in network byte
order. If the input is invalid, INADDR_NONE (usually -1) is returned. Use of this function is problematic because -1 is a valid
address (255.255.255.255). Avoid its use in favor of inet_aton(), inet_pton(3), or getaddrinfo(3) which provide a cleaner way to
indicate error return.
127.0.0.1是回送地址,指本地機,一般用來測試使用。
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3.傳輸數據
同創建服務端
服務器源代碼
#include <iostream>
#include <sys/types.h> //socket() , bind, accept, listen
#include <sys/socket.h> //socket() , bind, accept, listen
#include <netinet/in.h>
#include <unistd.h> //read(), write()
//#include <cstdlib>
#include <cstring> // memset
//#include <cstdio>
//#include <sys/stat.h>
#include <fcntl.h> // open
#define SERVER_PORT 12345
#define BUF_SIZE 4096
using namespace std;
int main(int argc, char ** argv)
{
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s < 0)
cerr<<"socket failed"<<endl;
struct sockaddr_in channel;
memset(&channel, 0, sizeof(channel));
channel.sin_family = AF_INET;
channel.sin_port = htons(SERVER_PORT);
channel.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (struct sockaddr*)&channel , sizeof(channel));
listen(s,5);
char buf[BUF_SIZE];
int acc = accept(s, 0,0);
char buf1[] = "test.txt";
int fd = open(buf1,O_CREAT | O_RDWR);
if(fd <0 )
return -1;
int byte = 0;
while( (byte = read(acc,buf,10) ) > 0 )
{
write(fd,buf,byte);
cout<<"receive something: "<<buf<<endl;
}
close(fd);
return 0;
}
客戶端代碼
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
//#include <netdb.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <sys/stat.h>
#include <fcntl.h>
#define SERVER_PORT 12345
#define BUF_SIZE 4096
using namespace std;
int main(int argc, char ** argv)
{
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s < 0)
cerr<<"socket failed"<<endl;
struct sockaddr_in channel;
memset(&channel, 0, sizeof(channel));
channel.sin_family = AF_INET;
channel.sin_port = htons(SERVER_PORT);
channel.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s, (struct sockaddr* )&channel, sizeof(channel));
char buf[BUF_SIZE] ;
// if(argc <= 1)
// return -1;
char buf1[] = "test.txt";
int fd = open(buf1, O_RDONLY);
//int fd = open(argv[1],O_RDONLY);
if(fd <0)
return -1;
int byte = 0;
while( (byte = read(fd,buf,BUF_SIZE) ) > 0)
{
cout<<"send something: "<<buf<<endl;
write(s,buf,strlen(buf) + 1);
}
close(fd);
return 0;
}