环境:服务器端用linux c编写,运行于linux mint18.
客户端用vs控制台编写,运行于Win 7.
Server端:
main.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h> /* for func: close */
#include <ctype.h>
#include "base_type.h"
#include "util_string.h"
#define MAX_BUF_LEN 1000
const INT g_iServerPort = 8000;
extern BOOL str_toUpper(IN CHAR *srcStr,OUT CHAR *dstStr);
int main()
{
struct sockaddr_in stSockIn;
struct sockaddr_in stSockClient;
INT sock_fd = 0; /* 监听socket */
INT sock_ConFd =0; /* 连接socket */
INT addr_size = 0;
CHAR RecvBuf[MAX_BUF_LEN]={0};
CHAR SendBuf[MAX_BUF_LEN]={0};
sock_fd = socket(AF_INET,SOCK_STREAM,0);
if ( -1 == sock_fd)
{
perror("Create socket failed.\n");
return -1;
}
memset(&stSockIn,0,sizeof(struct sockaddr_in));
memset(&stSockClient,0,sizeof(struct sockaddr_in));
stSockIn.sin_family = AF_INET;
stSockIn.sin_addr.s_addr = INADDR_ANY;
stSockIn.sin_port = htons(g_iServerPort);
if ( -1 == bind(sock_fd,(struct sockaddr *)&stSockIn,sizeof(stSockIn)) )
{
perror("Bind socket failed.\n");
return 0;
}
if ( -1 == listen(sock_fd,30) )
{
perror("Listen failed.\n");
return 0;
}
printf("---------server is accepting connection.------\n");
while ( 1 )
{
sock_ConFd= accept(sock_fd,(struct sockaddr *)&stSockClient,&addr_size);
if ( -1 == sock_ConFd)
{
perror("accept failed.\n");
break;
}
else
{
/* 获取已连接的client的地址信息 */
printf("The client IP(%s):Port(%d) connected.\n",
inet_ntoa(stSockClient.sin_addr),
ntohs(stSockClient.sin_port));
}
if ( -1 == recv(sock_ConFd,RecvBuf,MAX_BUF_LEN,0) )
{
perror("Server Recv failed.\n");
break;
}
printf("recv data : %s.\n",RecvBuf);
str_toUpper(RecvBuf,SendBuf);
/* send */
if ( -1 == send(sock_ConFd,SendBuf,strlen(SendBuf),0))
{
perror("Server send data failed!\n");
break;
}
close(sock_ConFd);
}
close(sock_fd);
return 0;
}
base_type.h文件
#ifndef BASE_TYPE_H
#define BASE_TYPE_H
#define UCHAR unsigned char
#define CHAR char
#define UINT unsigned int
#define INT int
#define ULONG unsigned long
typedef enum tagBOOL
{
FALSE=0,
TRUE
}BOOL;
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
#endif
util_string.h
#ifndef UTIL_STRING_H
#define UTIL_STRING_H
BOOL str_toUpper(IN CHAR *srcStr,OUT CHAR *dstStr);
BOOL str_toLower(IN CHAR * srcStr, OUT CHAR * dstStr);
#endif
util_string.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "util_string.h"
#include "base_type.h"
/*****************************************************************************
* 函 数 名 : str_toUpper
* 负 责 人 : zhaogang
* 创建日期 : 2016年9月15日
* 函数功能 : 将str中的小写字符转大写字符
* 输入参数 : IN CHAR * srcStr 源str
OUT CHAR * dstStr 结果str(调用者自己保证内存已分配)
* 输出参数 : 无
* 返 回 值 :
* 调用关系 :
* 其 它 :
*****************************************************************************/
BOOL str_toUpper(IN CHAR * srcStr, OUT CHAR * dstStr)
{
INT iIndex = 0;
if ( (NULL == srcStr) || (NULL == dstStr))
{
printf("Invalid params: p1(%p),p2(%p).",srcStr,dstStr);
return FALSE;
}
INT iSrcLen = strlen(srcStr);
for (iIndex = 0; iIndex <iSrcLen; iIndex++)
{
dstStr[iIndex] = (CHAR)toupper(srcStr[iIndex]);
}
dstStr[iIndex]='\0';
return TRUE;
}
/*****************************************************************************
* 函 数 名 : str_toLower
* 负 责 人 : zhaogang
* 创建日期 : 2016年9月15日
* 函数功能 : 将源字符串所有大写转小写
* 输入参数 : IN CHAR * srcStr 原始字符串
OUT CHAR * dstStr 转换后字符串
* 输出参数 : 无
* 返 回 值 :
* 调用关系 :
* 其 它 :
*****************************************************************************/
BOOL str_toLower(IN CHAR * srcStr, OUT CHAR * dstStr)
{
INT iIndex =0;
INT iSrcLen = 0;
if ( (NULL == srcStr) || (NULL == dstStr))
{
printf("Invalid params: p1(%p),p2(%p).",srcStr,dstStr);
return FALSE;
}
iSrcLen = strlen(srcStr);
for (iIndex = 0; iIndex<srcStr ; iIndex++)
{
dstStr[iIndex] = (CHAR)(tolower(srcStr[iIndex]));
}
dstStr[iIndex]='\0';
return TRUE;
}
client端:(win32 --直接抄的网上的)
#include <WINSOCK2.H>
#include <STDIO.H>
#pragma comment(lib,"ws2_32.lib")
#define MAX_BUF_LEN 1000
const int g_iServerPort = 8000;
const char g_szServerIP[] = "192.168.16.112";
int main(int argc, char* argv[])
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
return 0;
}
SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
printf("invalid socket !");
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(g_iServerPort);
serAddr.sin_addr.S_un.S_addr = inet_addr(g_szServerIP);
if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("connect error !");
closesocket(sclient);
return 0;
}
char * sendData = "this is client send data!";
send(sclient, sendData, strlen(sendData), 0);
char recData[MAX_BUF_LEN] = {0};
int ret = recv(sclient, recData, MAX_BUF_LEN, 0);
if (ret > 0)
{
recData[ret] = 0x00;
printf(recData);
}
closesocket(sclient);
WSACleanup();
return 0;
}
测试结果:
说明:
由于我有两台物理机,一台装的win7,一台装的linux mint,因此Client端连接的IP的地址是服务器的IP地址,如果装的虚拟机(双系统),用环回地址127.0.0.1测试。我主要是学习不同操作系统下内核编程,客户端直接copy过来,希望观众查找资料深入理解TCP连接步骤。
此外,写那么多文件是为了日后扩展,毕竟已经上班了,再不能没有规范的乱写代码了。谢谢。