跨平台函数定义
#ifdef WIN32
void init_socket() {
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) {
return;
}
}
int writesocket(int s, const char *buf, int len, int flags = 0) {
return send(s, buf, len, flags);
}
int readsocket(int s, char *buf, int len, int flags = 0) {
return recv(s, buf, len, flags);
}
void close_socket(int s = 0) {
closesocket(s);
WSACleanup();
}
#elif 1
void init_socket() {
}
int writesocket(int s, const char *buf, int len, int flags = 0) {
return write(s, buf, len);
}
int readsocket(int s, char *buf, int len, int flags = 0) {
return read(s, buf, len);
}
void close_socket(int s = 0) {
close(s);
}
#endif
tcp服务端:
如果客户端发送download命令,则给该客户端发送文件
#ifdef WIN32
#include <winsock2.h>
#include <WS2tcpip.h>
#include <Windows.h>
#elif 1
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#define _PORT_ 9999
#define SERVER_IP "127.0.0.1"
#define _BACKLOG_ 10
int is_begin_with(const char * str1,char *str2)
{
if(str1 == NULL || str2 == NULL)
return -1;
int len1 = strlen(str1);
int len2 = strlen(str2);
if((len1 < len2) || (len1 == 0 || len2 == 0))
return -1;
char *p = str2;
int i = 0;
while(*p != '\0')
{
if(*p != str1[i])
return 0;
p++;
i++;
}
return 1;
}
#ifdef WIN32
void init_socket() {
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) {
return;
}
}
int writesocket(int s, const char *buf, int len, int flags) {
return send(s, buf, len, flags);
}
int readsocket(int s, char *buf, int len, int flags) {
return recv(s, buf, len, flags);
}
void close_socket(int s) {
WSACleanup();
}
#elif 1
void init_socket() {
}
int writesocket(int s, const char *buf, int len, int flags) {
return write(s, buf, len);
}
int readsocket(int s, char *buf, int len, int flags) {
return read(s, buf, len);
}
void close_socket(int s) {
close(s);
}
#endif
int main()
{
#ifdef WIN32
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
return 0;
}
#elif 1
#define INVALID_SOCKET ~0
#endif
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("socket error !");
return 0;
}
struct sockaddr_in server_socket;
struct sockaddr_in client_socket;
memset(&server_socket, 0, sizeof(server_socket));
server_socket.sin_family = AF_INET;
server_socket.sin_port = htons(_PORT_);
server_socket.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock, (struct sockaddr *)&server_socket, sizeof(struct sockaddr_in)) < 0)
{
printf("bind error,error code is %d,error string is :%s\n",errno,strerror(errno));
close(sock);
return 1;
}
if(listen(sock,_BACKLOG_) < 0)
{
printf("listen error,error code is %d,error string is %s\n",errno,strerror(errno));
close(sock);
return 2;
}
printf("bind and listen success,wait accept...\n");
for(;;)
{
socklen_t len = sizeof(struct sockaddr);
int client_sock = accept(sock, (struct sockaddr *)&client_socket, &len);
if(client_sock == INVALID_SOCKET)
{
printf("accept error, error is %d,errstring is %s\n",errno,strerror(errno));
close(sock);
return 3;
}
char buf_ip[INET_ADDRSTRLEN];
memset(buf_ip,'\0',sizeof(buf_ip));
inet_ntop(AF_INET,&client_socket.sin_addr,buf_ip,sizeof(buf_ip));
printf("get connect,ip is %s,port is %d\n",buf_ip,ntohs(client_socket.sin_port));
char buf[1024];
memset(buf,'\0',sizeof(buf));//跟前面的初始化对比
readsocket(client_sock, buf, sizeof(buf), 0);
printf("client :# %s\n", buf);
// if(is_begin_with(buf, "download") != 1) {
// //printf("command unvalid!");
// continue;
// }
FILE *fp;
fp = fopen(buf, "rb");
fseek( fp , 0 , SEEK_END);
int size = ftell(fp);
writesocket(client_sock, (const char *)&size, sizeof(int), 0);
fseek( fp , 0 , SEEK_SET);
char buffer[4096];
int totalbytes = 0;
while(!feof(fp)){
len = fread(buffer, 1, sizeof(buffer), fp);
int bflen = writesocket(client_sock, buffer, len, 0);
totalbytes += len;
printf("write in bytes:%d, total written bytes:%d\n", bflen, totalbytes);
}
printf("write done, total bytes:%d\n", totalbytes);
}
close(sock);
return 0;
}
tcp客户端:
以二进制的方式接收文件
void DownloadService::test(const char *fileName)
{
init_socket();
struct sockaddr_in server_sock;
int sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_sock, 0, sizeof(server_sock));
server_sock.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_IP, &server_sock.sin_addr);
server_sock.sin_port = htons(SERVER_PORT);
int ret = ::connect(sock, (struct sockaddr*)&server_sock, sizeof(server_sock));
if(ret < 0)
{
printf("connect failed...,errno is %d,errstring is %s\n",errno,strerror(errno));
}
printf("connect sercer success !\n");
writesocket(sock, fileName, strlen(fileName), 0);
char localFileName[100] = "./zol/game/maroon/";
strcat(localFileName, "maroon.rcc");
FILE *pf;
pf = fopen(localFileName, "w+");
fclose(pf);
pf = fopen(localFileName, "wb");
int tl = 0;
int timeout = 3000;
//设置接收超时时间
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(int));
int i = 0;
int filesize = 0;
readsocket(sock, (char*)&filesize, sizeof(int), 0);
printf("get file size:%d\n", filesize);
while(true) {
char recvBuf[4096] = { 0 };
if(tl >= filesize)
break;
int len = readsocket(sock, recvBuf, 4096, 0);
if(len <= 0)
break;
tl += len;
printf("recv rcc part:%d, total bytes:%d\n", len, tl);
fwrite(recvBuf, len, 1, pf);
}
printf("recv done\n");
fclose(pf);
close_socket(sock);
}