为了简单,这个程序没有套接字的错误处理逻辑。原文件名跟传输后存储的文件名都是程序里写死的。
如果想得到更安全的网络编程例子,推荐 《网络编程 卷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;
}